Browse Source

Fix intrinsics being considered as overload candidates in namespace-qualified calls (#1886)

Tristan Labelle 6 years ago
parent
commit
f48fa9a1b6

+ 6 - 0
tools/clang/lib/Sema/SemaHLSL.cpp

@@ -4069,6 +4069,12 @@ public:
   {
     DXASSERT_NOMSG(ULE != nullptr);
 
+    // Intrinsics live in the global namespace, so references to their names
+    // should be either unqualified or '::'-prefixed.
+    if (ULE->getQualifier() && ULE->getQualifier()->getKind() != NestedNameSpecifier::Global) {
+      return false;
+    }
+
     const DeclarationNameInfo declName = ULE->getNameInfo();
     IdentifierInfo* idInfo = declName.getName().getAsIdentifierInfo();
     if (idInfo == nullptr)

+ 17 - 0
tools/clang/test/CodeGenHLSL/declarations/functions/overloading/intrinsic_overloading.hlsl

@@ -0,0 +1,17 @@
+// RUN: %dxc -E main -T vs_6_0 %s | FileCheck %s
+
+// Test that intrinsics can be overloaded without
+// shadowing the original definition.
+
+// CHECK: call void @dx.op.storeOutput.i32(i32 5, i32 0, i32 0, i8 0, i32 42)
+// CHECK: call void @dx.op.storeOutput.i32(i32 5, i32 0, i32 0, i8 1, i32 1)
+
+struct Struct { int x; };
+int abs(Struct s) { return 42; }
+
+int2 main() : OUT
+{
+    Struct s = { -1 };
+    return int2(abs(s), // Should call struct overload
+        abs(-1)); // Should call intrinsic
+}

+ 8 - 0
tools/clang/test/CodeGenHLSL/declarations/functions/overloading/intrinsic_shadowing.hlsl

@@ -0,0 +1,8 @@
+// RUN: %dxc -E main -T vs_6_0 %s | FileCheck %s | XFail GitHub #1887
+
+// Test that global functions can shadow intrinsics.
+
+// CHECK: call void @dx.op.storeOutput.i32(i32 5, i32 0, i32 0, i8 0, i32 42)
+
+int abs(int x) { return 42; }
+int main() : OUT { return abs(-1); }

+ 20 - 0
tools/clang/test/CodeGenHLSL/declarations/functions/overloading/namespace_qualified_no_intrinsic_candidate.hlsl

@@ -0,0 +1,20 @@
+// RUN: %dxc -E main -T vs_6_0 %s | FileCheck %s
+
+// Regression test for GitHub #1884, where intrinsics were considered
+// valid overload candidates for overloaded functions of the same name in a namespace
+
+// CHECK: call void @dx.op.storeOutput.i32(i32 5, i32 0, i32 0, i8 0, i32 42)
+// CHECK: call void @dx.op.storeOutput.i32(i32 5, i32 0, i32 0, i8 1, i32 13)
+
+namespace foo
+{
+    int abs(int2 x) { return 42; }
+    int abs() { return 13; }
+}
+
+int2 main() : OUT
+{
+    // This should not consider the abs(int) intrinsic from the global namespace,
+    // regardless of the fact that it is a better match for the arguments.
+    return int2(foo::abs(0), foo::abs());
+}