r193896 - Wraps lazily generated builtins in an extern "C" context
Warren Hunt
whunt at google.com
Fri Nov 1 16:46:52 PDT 2013
Author: whunt
Date: Fri Nov 1 18:46:51 2013
New Revision: 193896
URL: http://llvm.org/viewvc/llvm-project?rev=193896&view=rev
Log:
Wraps lazily generated builtins in an extern "C" context
Differential Revision: http://llvm-reviews.chandlerc.com/D2082
Adds a lang_c LinkageSpecDecl to lazily generated builtins. This enforces correct
behavior for builtins in a variety of cases without special treatment elsewhere within
the compiler (special treatment is removed by the patch). It also allows for C++
overloads of builtin functions, which Microsoft uses in their headers e.g.
_InterlockedExchangeAdd is an extern C builtin for the long type but an inline wrapper
for int type.
Modified:
cfe/trunk/lib/AST/Decl.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/test/CodeGenCXX/builtins.cpp
Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=193896&r1=193895&r2=193896&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Fri Nov 1 18:46:51 2013
@@ -2367,12 +2367,6 @@ bool FunctionDecl::isReplaceableGlobalAl
}
LanguageLinkage FunctionDecl::getLanguageLinkage() const {
- // Users expect to be able to write
- // extern "C" void *__builtin_alloca (size_t);
- // so consider builtins as having C language linkage.
- if (getBuiltinID())
- return CLanguageLinkage;
-
return getLanguageLinkageTemplate(*this);
}
@@ -2453,6 +2447,22 @@ unsigned FunctionDecl::getBuiltinID() co
return 0;
ASTContext &Context = getASTContext();
+ if (Context.getLangOpts().CPlusPlus) {
+ const LinkageSpecDecl *LinkageDecl = dyn_cast<LinkageSpecDecl>(
+ getFirstDecl()->getDeclContext());
+ // In C++, the first declaration of a builtin is always inside an implicit
+ // extern "C".
+ // FIXME: A recognised library function may not be directly in an extern "C"
+ // declaration, for instance "extern "C" { namespace std { decl } }".
+ if (!LinkageDecl || LinkageDecl->getLanguage() != LinkageSpecDecl::lang_c)
+ return 0;
+ }
+
+ // If the function is marked "overloadable", it has a different mangled name
+ // and is not the C library function.
+ if (getAttr<OverloadableAttr>())
+ return 0;
+
if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
return BuiltinID;
@@ -2464,22 +2474,7 @@ unsigned FunctionDecl::getBuiltinID() co
if (getStorageClass() == SC_Static)
return 0;
- // If this function is at translation-unit scope and we're not in
- // C++, it refers to the C library function.
- if (!Context.getLangOpts().CPlusPlus &&
- getDeclContext()->isTranslationUnit())
- return BuiltinID;
-
- // If the function is in an extern "C" linkage specification and is
- // not marked "overloadable", it's the real function.
- if (isa<LinkageSpecDecl>(getDeclContext()) &&
- cast<LinkageSpecDecl>(getDeclContext())->getLanguage()
- == LinkageSpecDecl::lang_c &&
- !getAttr<OverloadableAttr>())
- return BuiltinID;
-
- // Not a builtin
- return 0;
+ return BuiltinID;
}
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=193896&r1=193895&r2=193896&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Nov 1 18:46:51 2013
@@ -1534,8 +1534,17 @@ NamedDecl *Sema::LazilyCreateBuiltin(Ide
<< Context.BuiltinInfo.GetName(BID);
}
+ DeclContext *Parent = Context.getTranslationUnitDecl();
+ if (getLangOpts().CPlusPlus) {
+ LinkageSpecDecl *CLinkageDecl =
+ LinkageSpecDecl::Create(Context, Parent, Loc, Loc,
+ LinkageSpecDecl::lang_c, false);
+ Parent->addDecl(CLinkageDecl);
+ Parent = CLinkageDecl;
+ }
+
FunctionDecl *New = FunctionDecl::Create(Context,
- Context.getTranslationUnitDecl(),
+ Parent,
Loc, Loc, II, R, /*TInfo=*/0,
SC_Extern,
false,
@@ -1559,13 +1568,14 @@ NamedDecl *Sema::LazilyCreateBuiltin(Ide
}
AddKnownFunctionAttributes(New);
+ RegisterLocallyScopedExternCDecl(New, S);
// TUScope is the translation-unit scope to insert this function into.
// FIXME: This is hideous. We need to teach PushOnScopeChains to
// relate Scopes to DeclContexts, and probably eliminate CurContext
// entirely, but we're not there yet.
DeclContext *SavedContext = CurContext;
- CurContext = Context.getTranslationUnitDecl();
+ CurContext = Parent;
PushOnScopeChains(New, TUScope);
CurContext = SavedContext;
return New;
@@ -7608,7 +7618,7 @@ bool Sema::CheckFunctionDeclaration(Scop
// during delayed parsing anyway.
if (!CurContext->isRecord())
CheckCXXDefaultArguments(NewFD);
-
+
// If this function declares a builtin function, check the type of this
// declaration against the expected type for the builtin.
if (unsigned BuiltinID = NewFD->getBuiltinID()) {
@@ -7621,7 +7631,7 @@ bool Sema::CheckFunctionDeclaration(Scop
Context.BuiltinInfo.ForgetBuiltin(BuiltinID, Context.Idents);
}
}
-
+
// If this function is declared as being extern "C", then check to see if
// the function returns a UDT (class, struct, or union type) that is not C
// compatible, and if it does, warn the user.
Modified: cfe/trunk/test/CodeGenCXX/builtins.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/builtins.cpp?rev=193896&r1=193895&r2=193896&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/builtins.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/builtins.cpp Fri Nov 1 18:46:51 2013
@@ -15,3 +15,15 @@ S *addressof(bool b, S &s, S &t) {
// CHECK: ret {{.*}}* %[[LVALUE]]
return __builtin_addressof(b ? s : t);
}
+
+extern "C" int __builtin_abs(int); // #1
+long __builtin_abs(long); // #2
+extern "C" int __builtin_abs(int); // #3
+
+int x = __builtin_abs(-2);
+// CHECK: entry:
+// CHECK-NEXT: store i32 2, i32* @x, align 4
+
+long y = __builtin_abs(-2l);
+// CHECK: entry:
+// CHECK-NEXT: %call = call i32 @_Z13__builtin_absl(i32 -2)
More information about the cfe-commits
mailing list