summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2013-10-22 21:39:03 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2013-10-22 21:39:03 +0000
commitd53ffa0a70d807ec77969fa0168ced90ceaddd98 (patch)
tree6b26b1848a65f8c15b88f069a862cb275c24d8e2 /clang/lib/Sema/SemaDecl.cpp
parentf34568b0af4b1479727fd42101fb69b783ce4fe9 (diff)
downloadbcm5719-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.cpp61
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() &&
OpenPOWER on IntegriCloud