erichkeane updated this revision to Diff 141876.
erichkeane retitled this revision from "Strip reference from a va_list object 
in C when merging parameter types." to "Limit types of builtins that can be 
redeclared.".
erichkeane edited the summary of this revision.
erichkeane added a comment.

Eli's suggestion for implementation.


https://reviews.llvm.org/D45383

Files:
  include/clang/Basic/Builtins.h
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/Basic/Builtins.cpp
  lib/Sema/SemaDecl.cpp
  test/Sema/MicrosoftExtensions.c
  test/Sema/builtin-redecl.cpp
  test/SemaCXX/microsoft-varargs.cpp

Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -3014,6 +3014,14 @@
   if (Old->isInvalidDecl())
     return true;
 
+  // Disallow redeclaration of some builtins.
+  if (!getASTContext().BuiltinInfo.canBeRedeclared(Old->getBuiltinID())) {
+    Diag(New->getLocation(), diag::err_builtin_redeclare) << Old->getDeclName();
+    Diag(Old->getLocation(), diag::note_previous_builtin_declaration)
+        << Old << Old->getType();
+    return true;
+  }
+
   diag::kind PrevDiag;
   SourceLocation OldLocation;
   std::tie(PrevDiag, OldLocation) =
Index: lib/Basic/Builtins.cpp
===================================================================
--- lib/Basic/Builtins.cpp
+++ lib/Basic/Builtins.cpp
@@ -139,3 +139,9 @@
                                    bool &HasVAListArg) {
   return isLike(ID, FormatIdx, HasVAListArg, "sS");
 }
+
+bool Builtin::Context::canBeRedeclared(unsigned ID) const {
+  return ID == Builtin::NotBuiltin ||
+         (!hasReferenceArgsOrResult(ID) &&
+          !hasCustomTypechecking(ID));
+}
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -602,6 +602,7 @@
   "incompatible redeclaration of library function %0">,
   InGroup<DiagGroup<"incompatible-library-redeclaration">>;
 def err_builtin_definition : Error<"definition of builtin function %0">;
+def err_builtin_redeclare : Error<"cannot redeclare builtin function %0">;
 def err_arm_invalid_specialreg : Error<"invalid special register for builtin">;
 def err_invalid_cpu_supports : Error<"invalid cpu feature string for builtin">;
 def err_invalid_cpu_is : Error<"invalid cpu name for builtin">;
Index: include/clang/Basic/Builtins.h
===================================================================
--- include/clang/Basic/Builtins.h
+++ include/clang/Basic/Builtins.h
@@ -167,6 +167,13 @@
     return strchr(getRecord(ID).Type, '*') != nullptr;
   }
 
+  /// \brief Return true if this builtin has a result or any arguments which are
+  /// reference types.
+  bool hasReferenceArgsOrResult(unsigned ID) const {
+    return strchr(getRecord(ID).Type, '&') != nullptr ||
+           strchr(getRecord(ID).Type, 'A') != nullptr;
+  }
+
   /// \brief Completely forget that the given ID was ever considered a builtin,
   /// e.g., because the user provided a conflicting signature.
   void forgetBuiltin(unsigned ID, IdentifierTable &Table);
@@ -212,6 +219,10 @@
   /// prefix.
   static bool isBuiltinFunc(const char *Name);
 
+  /// Returns true if this is a builtin that can be redeclared.  Returns true
+  /// for non-builtins.
+  bool canBeRedeclared(unsigned ID) const;
+
 private:
   const Info &getRecord(unsigned ID) const;
 
Index: test/SemaCXX/microsoft-varargs.cpp
===================================================================
--- test/SemaCXX/microsoft-varargs.cpp
+++ test/SemaCXX/microsoft-varargs.cpp
@@ -3,7 +3,6 @@
 
 extern "C" {
 typedef char * va_list;
-void __va_start(va_list *, ...);
 }
 
 int test___va_start(int i, ...) {
Index: test/Sema/MicrosoftExtensions.c
===================================================================
--- test/Sema/MicrosoftExtensions.c
+++ test/Sema/MicrosoftExtensions.c
@@ -166,7 +166,6 @@
 T __ptr32 wrong10; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
 
 typedef char *my_va_list;
-void __va_start(my_va_list *ap, ...); // expected-note {{passing argument to parameter 'ap' here}}
 void vmyprintf(const char *f, my_va_list ap);
 void myprintf(const char *f, ...) {
   my_va_list ap;
Index: test/Sema/builtin-redecl.cpp
===================================================================
--- test/Sema/builtin-redecl.cpp
+++ test/Sema/builtin-redecl.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 %s -fsyntax-only -verify 
+// RUN: %clang_cc1 %s -fsyntax-only -verify -x c
+
+// Redeclaring library builtins is OK.
+void exit(int);
+
+#if __cplusplus
+// Overloading a builtin is acceptable in C++.
+void __builtin_va_copy(double d);
+#endif
+
+// expected-error@+2 {{cannot redeclare builtin function '__builtin_va_end'}}
+// expected-note@+1 {{'__builtin_va_end' is a builtin with type}}
+void __builtin_va_end(__builtin_va_list);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to