erichkeane updated this revision to Diff 141900.
erichkeane marked an inline comment as done.
erichkeane added a comment.
Restrict overloads as well.
https://reviews.llvm.org/D45383
Files:
include/clang/AST/ASTContext.h
include/clang/Basic/Builtins.h
include/clang/Basic/DiagnosticSemaKinds.td
lib/AST/ASTContext.cpp
lib/Basic/Builtins.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaOverload.cpp
test/Sema/MicrosoftExtensions.c
test/Sema/builtin-redecl.cpp
test/SemaCXX/microsoft-varargs.cpp
Index: lib/AST/ASTContext.cpp
===================================================================
--- lib/AST/ASTContext.cpp
+++ lib/AST/ASTContext.cpp
@@ -7244,6 +7244,10 @@
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!");
Index: lib/Sema/SemaOverload.cpp
===================================================================
--- lib/Sema/SemaOverload.cpp
+++ lib/Sema/SemaOverload.cpp
@@ -998,6 +998,13 @@
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.
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().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) =
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/AST/ASTContext.h
===================================================================
--- include/clang/AST/ASTContext.h
+++ include/clang/AST/ASTContext.h
@@ -1881,6 +1881,10 @@
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 {
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,13 @@
+// RUN: %clang_cc1 %s -fsyntax-only -verify
+// RUN: %clang_cc1 %s -fsyntax-only -verify -x c
+
+// Redeclaring library builtins is OK.
+void exit(int);
+
+// expected-error@+2 {{cannot redeclare builtin function '__builtin_va_copy'}}
+// expected-note@+1 {{'__builtin_va_copy' is a builtin with type}}
+void __builtin_va_copy(double d);
+
+// 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
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits