r330160 - Limit types of builtins that can be redeclared.

Erich Keane via cfe-commits cfe-commits at lists.llvm.org
Mon Apr 16 14:30:08 PDT 2018


Author: erichkeane
Date: Mon Apr 16 14:30:08 2018
New Revision: 330160

URL: http://llvm.org/viewvc/llvm-project?rev=330160&view=rev
Log:
Limit types of builtins that can be redeclared.

As reported here: https://bugs.llvm.org/show_bug.cgi?id=37033
Any usage of a builtin function that uses a va_list by reference
will cause an assertion when redeclaring it.

After discussion in the review, it was concluded that the correct
way of accomplishing this fix is to make attempts to redeclare certain
builtins an error. Unfortunately, doing this limitation for all builtins
is likely a breaking change, so this commit simply limits it to
types with custom type checking and those that take a reference.

Two tests needed to be updated to make this work.

Differential Revision: https://reviews.llvm.org/D45383


Added:
    cfe/trunk/test/Sema/builtin-redecl.cpp   (with props)
Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/Basic/Builtins.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/Basic/Builtins.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=330160&r1=330159&r2=330160&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Mon Apr 16 14:30:08 2018
@@ -1881,6 +1881,10 @@ public:
     return getTypeDeclType(getBuiltinMSVaListDecl());
   }
 
+  /// Return whether a declaration to a builtin is allowed to be
+  /// overloaded/redeclared.
+  bool canBuiltinBeRedeclared(const FunctionDecl *) const;
+
   /// \brief Return a type with additional \c const, \c volatile, or
   /// \c restrict qualifiers.
   QualType getCVRQualifiedType(QualType T, unsigned CVR) const {

Modified: cfe/trunk/include/clang/Basic/Builtins.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Builtins.h?rev=330160&r1=330159&r2=330160&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Builtins.h (original)
+++ cfe/trunk/include/clang/Basic/Builtins.h Mon Apr 16 14:30:08 2018
@@ -167,6 +167,13 @@ public:
     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 @@ public:
   /// 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;
 

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=330160&r1=330159&r2=330160&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Apr 16 14:30:08 2018
@@ -602,6 +602,7 @@ def warn_redecl_library_builtin : Warnin
   "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">;

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=330160&r1=330159&r2=330160&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Mon Apr 16 14:30:08 2018
@@ -7244,6 +7244,10 @@ TypedefDecl *ASTContext::getBuiltinMSVaL
   return BuiltinMSVaListDecl;
 }
 
+bool ASTContext::canBuiltinBeRedeclared(const FunctionDecl *FD) const {
+  return BuiltinInfo.canBeRedeclared(FD->getBuiltinID());
+}
+
 void ASTContext::setObjCConstantStringInterface(ObjCInterfaceDecl *Decl) {
   assert(ObjCConstantStringType.isNull() &&
          "'NSConstantString' type already set!");

Modified: cfe/trunk/lib/Basic/Builtins.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Builtins.cpp?rev=330160&r1=330159&r2=330160&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/Builtins.cpp (original)
+++ cfe/trunk/lib/Basic/Builtins.cpp Mon Apr 16 14:30:08 2018
@@ -139,3 +139,10 @@ bool Builtin::Context::isScanfLike(unsig
                                    bool &HasVAListArg) {
   return isLike(ID, FormatIdx, HasVAListArg, "sS");
 }
+
+bool Builtin::Context::canBeRedeclared(unsigned ID) const {
+  return ID == Builtin::NotBuiltin ||
+         ID == Builtin::BI__va_start ||
+         (!hasReferenceArgsOrResult(ID) &&
+          !hasCustomTypechecking(ID));
+}

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=330160&r1=330159&r2=330160&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Apr 16 14:30:08 2018
@@ -3011,6 +3011,14 @@ bool Sema::MergeFunctionDecl(FunctionDec
   if (Old->isInvalidDecl())
     return true;
 
+  // Disallow redeclaration of some builtins.
+  if (!getASTContext().canBuiltinBeRedeclared(Old)) {
+    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) =

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=330160&r1=330159&r2=330160&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Mon Apr 16 14:30:08 2018
@@ -998,6 +998,13 @@ Sema::CheckOverload(Scope *S, FunctionDe
         Match = *I;
         return Ovl_Match;
       }
+
+      // Builtins that have custom typechecking or have a reference should
+      // not be overloadable or redeclarable.
+      if (!getASTContext().canBuiltinBeRedeclared(OldF)) {
+        Match = *I;
+        return Ovl_NonFunction;
+      }
     } else if (isa<UsingDecl>(OldD) || isa<UsingPackDecl>(OldD)) {
       // We can overload with these, which can show up when doing
       // redeclaration checks for UsingDecls.

Added: cfe/trunk/test/Sema/builtin-redecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/builtin-redecl.cpp?rev=330160&view=auto
==============================================================================
--- cfe/trunk/test/Sema/builtin-redecl.cpp (added)
+++ cfe/trunk/test/Sema/builtin-redecl.cpp Mon Apr 16 14:30:08 2018
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 %s -fsyntax-only -verify 
+// RUN: %clang_cc1 %s -fsyntax-only -verify -x c
+// RUN: %clang_cc1 %s -fsyntax-only -verify -fms-compatibility
+
+// Redeclaring library builtins is OK.
+void exit(int);
+
+// expected-error at +2 {{cannot redeclare builtin function '__builtin_va_copy'}}
+// expected-note at +1 {{'__builtin_va_copy' is a builtin with type}}
+void __builtin_va_copy(double d);
+
+// expected-error at +2 {{cannot redeclare builtin function '__builtin_va_end'}}
+// expected-note at +1 {{'__builtin_va_end' is a builtin with type}}
+void __builtin_va_end(__builtin_va_list);
+// RUN: %clang_cc1 %s -fsyntax-only -verify 
+// RUN: %clang_cc1 %s -fsyntax-only -verify -x c
+
+void __va_start(__builtin_va_list*, ...);

Propchange: cfe/trunk/test/Sema/builtin-redecl.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/Sema/builtin-redecl.cpp
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Rev URL

Propchange: cfe/trunk/test/Sema/builtin-redecl.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain




More information about the cfe-commits mailing list