aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2011-09-07 04:05:06 +0000
committerEli Friedman <eli.friedman@gmail.com>2011-09-07 04:05:06 +0000
commit900693b715b3832a42ae87157332baece94ccdd8 (patch)
tree770561d1ff4dfb104761e7cdb264b38e245d290c
parent6015969a51a500701f0acf15f3aa9d4010de4aa2 (diff)
Make sure the FunctionDecl's created by "#pragma weak" have correct ParmVarDecl's. PR10878.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@139224 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Sema/Sema.h3
-rw-r--r--lib/Sema/SemaDeclAttr.cpp39
-rw-r--r--test/CodeGen/pragma-weak.c15
3 files changed, 44 insertions, 13 deletions
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 1437469aeb..423f29f278 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -5324,7 +5324,8 @@ public:
void ActOnPragmaVisibility(bool IsPush, const IdentifierInfo* VisType,
SourceLocation PragmaLoc);
- NamedDecl *DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II);
+ NamedDecl *DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II,
+ SourceLocation Loc);
void DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W);
/// ActOnPragmaWeakID - Called on well formed #pragma weak ident.
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 0483552c51..1119866352 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -3631,17 +3631,40 @@ void Sema::ProcessDeclAttributeList(Scope *S, Decl *D,
/// DeclClonePragmaWeak - clone existing decl (maybe definition),
/// #pragma weak needs a non-definition decl and source may not have one
-NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II) {
+NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II,
+ SourceLocation Loc) {
assert(isa<FunctionDecl>(ND) || isa<VarDecl>(ND));
NamedDecl *NewD = 0;
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
- NewD = FunctionDecl::Create(FD->getASTContext(), FD->getDeclContext(),
- FD->getInnerLocStart(),
- FD->getLocation(), DeclarationName(II),
- FD->getType(), FD->getTypeSourceInfo());
- if (FD->getQualifier()) {
- FunctionDecl *NewFD = cast<FunctionDecl>(NewD);
+ FunctionDecl *NewFD;
+ // FIXME: Missing call to CheckFunctionDeclaration().
+ // FIXME: Mangling?
+ // FIXME: Is the qualifier info correct?
+ // FIXME: Is the DeclContext correct?
+ NewFD = FunctionDecl::Create(FD->getASTContext(), FD->getDeclContext(),
+ Loc, Loc, DeclarationName(II),
+ FD->getType(), FD->getTypeSourceInfo(),
+ SC_None, SC_None,
+ false/*isInlineSpecified*/,
+ FD->hasPrototype(),
+ false/*isConstexprSpecified*/);
+ NewD = NewFD;
+
+ if (FD->getQualifier())
NewFD->setQualifierInfo(FD->getQualifierLoc());
+
+ // Fake up parameter variables; they are declared as if this were
+ // a typedef.
+ QualType FDTy = FD->getType();
+ if (const FunctionProtoType *FT = FDTy->getAs<FunctionProtoType>()) {
+ SmallVector<ParmVarDecl*, 16> Params;
+ for (FunctionProtoType::arg_type_iterator AI = FT->arg_type_begin(),
+ AE = FT->arg_type_end(); AI != AE; ++AI) {
+ ParmVarDecl *Param = BuildParmVarDeclForTypedef(NewFD, Loc, *AI);
+ Param->setScopeInfo(0, Params.size());
+ Params.push_back(Param);
+ }
+ NewFD->setParams(Params.data(), Params.size());
}
} else if (VarDecl *VD = dyn_cast<VarDecl>(ND)) {
NewD = VarDecl::Create(VD->getASTContext(), VD->getDeclContext(),
@@ -3664,7 +3687,7 @@ void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W) {
W.setUsed(true);
if (W.getAlias()) { // clone decl, impersonate __attribute(weak,alias(...))
IdentifierInfo *NDId = ND->getIdentifier();
- NamedDecl *NewD = DeclClonePragmaWeak(ND, W.getAlias());
+ NamedDecl *NewD = DeclClonePragmaWeak(ND, W.getAlias(), W.getLocation());
NewD->addAttr(::new (Context) AliasAttr(W.getLocation(), Context,
NDId->getName()));
NewD->addAttr(::new (Context) WeakAttr(W.getLocation(), Context));
diff --git a/test/CodeGen/pragma-weak.c b/test/CodeGen/pragma-weak.c
index 1de60e106a..7ad2b77d8e 100644
--- a/test/CodeGen/pragma-weak.c
+++ b/test/CodeGen/pragma-weak.c
@@ -136,7 +136,7 @@ void __both3(void) {}
void __a1(void) __attribute((noinline));
#pragma weak a1 = __a1
void __a1(void) {}
-// CHECK: define void @__a1()
+// CHECK: define void @__a1() {{.*}} noinline
// attributes introduced BEFORE a combination of #pragma weak and alias()
// hold...
@@ -144,13 +144,20 @@ void __a3(void) __attribute((noinline));
#pragma weak a3 = __a3
void a3(void) __attribute((alias("__a3")));
void __a3(void) {}
-// CHECK: define void @__a3()
+// CHECK: define void @__a3() {{.*}} noinline
#pragma weak xxx = __xxx
__attribute((pure,noinline,const,fastcall)) void __xxx(void) { }
-// CHECK: void @__xxx()
+// CHECK: void @__xxx() {{.*}} noinline
-/// TODO: stuff that still doesn't work
+///////////// PR10878: Make sure we can call a weak alias
+void SHA512Pad(void *context) {}
+#pragma weak SHA384Pad = SHA512Pad
+void PR10878() { SHA384Pad(0); }
+// CHECK: call void @SHA384Pad(i8* null)
+
+
+///////////// TODO: stuff that still doesn't work
// due to the fact that disparate TopLevelDecls cannot affect each other
// (due to clang's Parser and ASTConsumer behavior, and quite reasonable)