[c++1z] PR31210: ignore exception specification when matching the type of a
authorRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 29 Nov 2016 22:32:05 +0000 (22:32 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 29 Nov 2016 22:32:05 +0000 (22:32 +0000)
builtin with the type of an explicit declaration of the same function.

llvm-svn: 288208

clang/lib/Sema/SemaDecl.cpp
clang/test/SemaCXX/cxx1z-noexcept-function-type.cpp

index e8764a0..e2951cf 100644 (file)
@@ -9028,9 +9028,25 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
       LookupPredefedObjCSuperType(*this, S, NewFD->getIdentifier());
       QualType T = Context.GetBuiltinType(BuiltinID, Error);
       if (!T.isNull() && !Context.hasSameType(T, NewFD->getType())) {
-        // The type of this function differs from the type of the builtin,
-        // so forget about the builtin entirely.
-        Context.BuiltinInfo.forgetBuiltin(BuiltinID, Context.Idents);
+        auto WithoutExceptionSpec = [&](QualType T) -> QualType {
+          auto *Proto = T->getAs<FunctionProtoType>();
+          if (!Proto)
+            return T;
+          return Context.getFunctionType(
+              Proto->getReturnType(), Proto->getParamTypes(),
+              Proto->getExtProtoInfo().withExceptionSpec(EST_None));
+        };
+
+        // If the type of the builtin differs only in its exception
+        // specification, that's OK.
+        // FIXME: If the types do differ in this way, it would be better to
+        // retain the 'noexcept' form of the type.
+        if (!getLangOpts().CPlusPlus1z ||
+            !Context.hasSameType(WithoutExceptionSpec(T),
+                                 WithoutExceptionSpec(NewFD->getType())))
+          // The type of this function differs from the type of the builtin,
+          // so forget about the builtin entirely.
+          Context.BuiltinInfo.forgetBuiltin(BuiltinID, Context.Idents);
       }
     }
 
index ae686d3..d9233e6 100644 (file)
@@ -97,3 +97,13 @@ namespace ImplicitExceptionSpec {
   };
   S::~S() {}
 }
+
+namespace Builtins {
+  // Pick two functions that ought to have the same noexceptness.
+  extern "C" int strcmp(const char *, const char *);
+  extern "C" int strncmp(const char *, const char *, decltype(sizeof(0))) noexcept;
+
+  // Check we recognized both as builtins.
+  typedef int arr[strcmp("bar", "foo") + 4 * strncmp("foo", "bar", 4)];
+  typedef int arr[3];
+}