diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2013-10-22 21:39:03 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2013-10-22 21:39:03 +0000 |
commit | d53ffa0a70d807ec77969fa0168ced90ceaddd98 (patch) | |
tree | 6b26b1848a65f8c15b88f069a862cb275c24d8e2 /clang/lib/Sema/SemaDecl.cpp | |
parent | f34568b0af4b1479727fd42101fb69b783ce4fe9 (diff) | |
download | bcm5719-llvm-d53ffa0a70d807ec77969fa0168ced90ceaddd98.tar.gz bcm5719-llvm-d53ffa0a70d807ec77969fa0168ced90ceaddd98.zip |
Treat aliases as definitions.
This fixes pr17639.
Before this patch clang would consider
void foo(void) __attribute((alias("__foo")));
a declaration. It now correctly handles it as a definition.
Initial patch by Alp Toker. I added support for variables.
llvm-svn: 193200
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 61 |
1 files changed, 54 insertions, 7 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 325366bef7f..d19d2c42a9d 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -1996,11 +1996,15 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D, InheritableAttr *Attr, static const Decl *getDefinition(const Decl *D) { if (const TagDecl *TD = dyn_cast<TagDecl>(D)) return TD->getDefinition(); - if (const VarDecl *VD = dyn_cast<VarDecl>(D)) - return VD->getDefinition(); + if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { + const VarDecl *Def = VD->getDefinition(); + if (Def) + return Def; + return VD->getActingDefinition(); + } if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { const FunctionDecl* Def; - if (FD->hasBody(Def)) + if (FD->isDefined(Def)) return Def; } return NULL; @@ -2029,6 +2033,32 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) { AttrVec &NewAttributes = New->getAttrs(); for (unsigned I = 0, E = NewAttributes.size(); I != E;) { const Attr *NewAttribute = NewAttributes[I]; + + if (isa<AliasAttr>(NewAttribute)) { + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(New)) + S.CheckForFunctionRedefinition(FD, cast<FunctionDecl>(Def)); + else { + VarDecl *VD = cast<VarDecl>(New); + unsigned Diag = cast<VarDecl>(Def)->isThisDeclarationADefinition() == + VarDecl::TentativeDefinition + ? diag::err_alias_after_tentative + : diag::err_redefinition; + S.Diag(VD->getLocation(), Diag) << VD->getDeclName(); + S.Diag(Def->getLocation(), diag::note_previous_definition); + VD->setInvalidDecl(); + } + ++I; + continue; + } + + if (const VarDecl *VD = dyn_cast<VarDecl>(Def)) { + // Tentative definitions are only interesting for the alias check above. + if (VD->isThisDeclarationADefinition() != VarDecl::Definition) { + ++I; + continue; + } + } + if (hasAttribute(Def, NewAttribute->getKind())) { ++I; continue; // regular attr merging will take care of validating this. @@ -8819,6 +8849,18 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) { } } + if (!VD->isInvalidDecl() && + VD->isThisDeclarationADefinition() == VarDecl::TentativeDefinition) { + if (const VarDecl *Def = VD->getDefinition()) { + if (Def->hasAttr<AliasAttr>()) { + Diag(VD->getLocation(), diag::err_tentative_after_alias) + << VD->getDeclName(); + Diag(Def->getLocation(), diag::note_previous_definition); + VD->setInvalidDecl(); + } + } + } + const DeclContext *DC = VD->getDeclContext(); // If there's a #pragma GCC visibility in scope, and this isn't a class // member, set the visibility of this variable. @@ -9323,12 +9365,17 @@ static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD, return MissingPrototype; } -void Sema::CheckForFunctionRedefinition(FunctionDecl *FD) { +void +Sema::CheckForFunctionRedefinition(FunctionDecl *FD, + const FunctionDecl *EffectiveDefinition) { // Don't complain if we're in GNU89 mode and the previous definition // was an extern inline function. - const FunctionDecl *Definition; - if (!FD->isDefined(Definition) || - canRedefineFunction(Definition, getLangOpts())) + const FunctionDecl *Definition = EffectiveDefinition; + if (!Definition) + if (!FD->isDefined(Definition)) + return; + + if (canRedefineFunction(Definition, getLangOpts())) return; if (getLangOpts().GNUMode && Definition->isInlineSpecified() && |