return false;
}
+bool Sema::mergeDeclAttribute(Decl *D, InheritableAttr *Attr) {
+ if (AvailabilityAttr *AA = dyn_cast<AvailabilityAttr>(Attr))
+ return mergeAvailabilityAttr(D, AA->getRange(), true, AA->getPlatform(),
+ AA->getIntroduced(), AA->getDeprecated(),
+ AA->getObsoleted(), AA->getUnavailable(),
+ AA->getMessage());
+
+ if (VisibilityAttr *VA = dyn_cast<VisibilityAttr>(Attr))
+ return mergeVisibilityAttr(D, VA->getRange(), true, VA->getVisibility());
+
+ if (DLLImportAttr *ImportA = dyn_cast<DLLImportAttr>(Attr))
+ return mergeDLLImportAttr(D, ImportA->getRange(), true);
+
+ if (DLLExportAttr *ExportA = dyn_cast<DLLExportAttr>(Attr))
+ return mergeDLLExportAttr(D, ExportA->getRange(), true);
+
+ if (!DeclHasAttr(D, Attr)) {
+ InheritableAttr *NewAttr = cast<InheritableAttr>(Attr->clone(Context));
+ NewAttr->setInherited(true);
+ D->addAttr(NewAttr);
+ return true;
+ }
+
+ return false;
+}
+
/// mergeDeclAttributes - Copy attributes from the Old decl to the New one.
void Sema::mergeDeclAttributes(Decl *New, Decl *Old,
bool MergeDeprecation) {
isa<AvailabilityAttr>(*i)))
continue;
- if (!DeclHasAttr(New, *i)) {
- InheritableAttr *newAttr = cast<InheritableAttr>((*i)->clone(Context));
- newAttr->setInherited(true);
- New->addAttr(newAttr);
+ if (mergeDeclAttribute(New, *i))
foundAny = true;
- }
}
if (!foundAny) New->dropAttrs();
NewFD->setInvalidDecl();
}
+ // Handle attributes.
+ ProcessDeclAttributes(S, NewFD, D,
+ /*NonInheritable=*/false, /*Inheritable=*/true);
+
if (!getLangOpts().CPlusPlus) {
// Perform semantic checking on the function declaration.
bool isExplicitSpecialization=false;
<< D.getCXXScopeSpec().getRange();
}
}
-
-
- // Handle attributes. We need to have merged decls when handling attributes
- // (for example to check for conflicts, etc).
- // FIXME: This needs to happen before we merge declarations. Then,
- // let attribute merging cope with attribute conflicts.
- ProcessDeclAttributes(S, NewFD, D,
- /*NonInheritable=*/false, /*Inheritable=*/true);
// attributes declared post-definition are currently ignored
// FIXME: This should happen during attribute merging
InFunctionDeclarator && Name)
DeclsInPrototypeScope.push_back(New);
+ if (PrevDecl)
+ mergeDeclAttributes(New, PrevDecl);
+
OwnedDecl = true;
return New;
}
return false;
}
-static void mergeAvailabilityAttr(Sema &S, Decl *D, SourceRange Range,
- IdentifierInfo *Platform,
- VersionTuple Introduced,
- VersionTuple Deprecated,
- VersionTuple Obsoleted,
- bool IsUnavailable,
- StringRef Message) {
- VersionTuple MergedIntroduced;
- VersionTuple MergedDeprecated;
- VersionTuple MergedObsoleted;
+bool Sema::mergeAvailabilityAttr(Decl *D, SourceRange Range,
+ bool Inherited,
+ IdentifierInfo *Platform,
+ VersionTuple Introduced,
+ VersionTuple Deprecated,
+ VersionTuple Obsoleted,
+ bool IsUnavailable,
+ StringRef Message) {
+ VersionTuple MergedIntroduced = Introduced;
+ VersionTuple MergedDeprecated = Deprecated;
+ VersionTuple MergedObsoleted = Obsoleted;
bool FoundAny = false;
- for (specific_attr_iterator<AvailabilityAttr>
- i = D->specific_attr_begin<AvailabilityAttr>(),
- e = D->specific_attr_end<AvailabilityAttr>();
- i != e ; ++i) {
- const AvailabilityAttr *OldAA = *i;
- IdentifierInfo *OldPlatform = OldAA->getPlatform();
- if (OldPlatform != Platform)
- continue;
- FoundAny = true;
- VersionTuple OldIntroduced = OldAA->getIntroduced();
- VersionTuple OldDeprecated = OldAA->getDeprecated();
- VersionTuple OldObsoleted = OldAA->getObsoleted();
- bool OldIsUnavailable = OldAA->getUnavailable();
- StringRef OldMessage = OldAA->getMessage();
-
- if ((!OldIntroduced.empty() && !Introduced.empty() &&
- OldIntroduced != Introduced) ||
- (!OldDeprecated.empty() && !Deprecated.empty() &&
- OldDeprecated != Deprecated) ||
- (!OldObsoleted.empty() && !Obsoleted.empty() &&
- OldObsoleted != Obsoleted) ||
- (OldIsUnavailable != IsUnavailable) ||
- (OldMessage != Message)) {
- S.Diag(Range.getBegin(), diag::warn_mismatched_availability);
- S.Diag(OldAA->getLocation(), diag::note_previous_attribute);
- return;
+ if (D->hasAttrs()) {
+ AttrVec &Attrs = D->getAttrs();
+ for (unsigned i = 0, e = Attrs.size(); i != e;) {
+ const AvailabilityAttr *OldAA = dyn_cast<AvailabilityAttr>(Attrs[i]);
+ if (!OldAA) {
+ ++i;
+ continue;
+ }
+
+ IdentifierInfo *OldPlatform = OldAA->getPlatform();
+ if (OldPlatform != Platform) {
+ ++i;
+ continue;
+ }
+
+ FoundAny = true;
+ VersionTuple OldIntroduced = OldAA->getIntroduced();
+ VersionTuple OldDeprecated = OldAA->getDeprecated();
+ VersionTuple OldObsoleted = OldAA->getObsoleted();
+ bool OldIsUnavailable = OldAA->getUnavailable();
+ StringRef OldMessage = OldAA->getMessage();
+
+ if ((!OldIntroduced.empty() && !Introduced.empty() &&
+ OldIntroduced != Introduced) ||
+ (!OldDeprecated.empty() && !Deprecated.empty() &&
+ OldDeprecated != Deprecated) ||
+ (!OldObsoleted.empty() && !Obsoleted.empty() &&
+ OldObsoleted != Obsoleted) ||
+ (OldIsUnavailable != IsUnavailable) ||
+ (OldMessage != Message)) {
+ Diag(OldAA->getLocation(), diag::warn_mismatched_availability);
+ Diag(Range.getBegin(), diag::note_previous_attribute);
+ Attrs.erase(Attrs.begin() + i);
+ --e;
+ continue;
+ }
+
+ VersionTuple MergedIntroduced2 = MergedIntroduced;
+ VersionTuple MergedDeprecated2 = MergedDeprecated;
+ VersionTuple MergedObsoleted2 = MergedObsoleted;
+
+ if (MergedIntroduced2.empty())
+ MergedIntroduced2 = OldIntroduced;
+ if (MergedDeprecated2.empty())
+ MergedDeprecated2 = OldDeprecated;
+ if (MergedObsoleted2.empty())
+ MergedObsoleted2 = OldObsoleted;
+
+ if (checkAvailabilityAttr(*this, OldAA->getRange(), Platform,
+ MergedIntroduced2, MergedDeprecated2,
+ MergedObsoleted2)) {
+ Attrs.erase(Attrs.begin() + i);
+ --e;
+ continue;
+ }
+
+ MergedIntroduced = MergedIntroduced2;
+ MergedDeprecated = MergedDeprecated2;
+ MergedObsoleted = MergedObsoleted2;
+ ++i;
}
- if (MergedIntroduced.empty())
- MergedIntroduced = OldIntroduced;
- if (MergedDeprecated.empty())
- MergedDeprecated = OldDeprecated;
- if (MergedObsoleted.empty())
- MergedObsoleted = OldObsoleted;
}
if (FoundAny &&
MergedIntroduced == Introduced &&
MergedDeprecated == Deprecated &&
MergedObsoleted == Obsoleted)
- return;
-
- if (MergedIntroduced.empty())
- MergedIntroduced = Introduced;
- if (MergedDeprecated.empty())
- MergedDeprecated = Deprecated;
- if (MergedObsoleted.empty())
- MergedObsoleted = Obsoleted;
+ return false;
- if (!checkAvailabilityAttr(S, Range, Platform, MergedIntroduced,
+ if (!checkAvailabilityAttr(*this, Range, Platform, MergedIntroduced,
MergedDeprecated, MergedObsoleted)) {
- D->addAttr(::new (S.Context) AvailabilityAttr(Range, S.Context,
- Platform,
- Introduced,
- Deprecated,
- Obsoleted,
- IsUnavailable,
- Message));
+ AvailabilityAttr *Attr =
+ ::new (Context) AvailabilityAttr(Range, Context, Platform,
+ Introduced, Deprecated,
+ Obsoleted, IsUnavailable, Message);
+
+ if (Inherited)
+ Attr->setInherited(true);
+ D->addAttr(Attr);
+ return true;
}
+ return false;
}
static void handleAvailabilityAttr(Sema &S, Decl *D,
if (SE)
Str = SE->getString();
- mergeAvailabilityAttr(S, D, Attr.getRange(),
- Platform,
- Introduced.Version,
- Deprecated.Version,
- Obsoleted.Version,
- IsUnavailable,
- Str);
+ S.mergeAvailabilityAttr(D, Attr.getRange(),
+ false, Platform,
+ Introduced.Version,
+ Deprecated.Version,
+ Obsoleted.Version,
+ IsUnavailable,
+ Str);
+}
+
+bool Sema::mergeVisibilityAttr(Decl *D, SourceRange Range,
+ bool Inherited,
+ VisibilityAttr::VisibilityType Vis) {
+ VisibilityAttr *ExistingAttr = D->getAttr<VisibilityAttr>();
+ if (ExistingAttr) {
+ VisibilityAttr::VisibilityType ExistingVis = ExistingAttr->getVisibility();
+ if (ExistingVis == Vis)
+ return false;
+ Diag(ExistingAttr->getLocation(), diag::err_mismatched_visibility);
+ Diag(Range.getBegin(), diag::note_previous_attribute);
+ D->dropAttr<VisibilityAttr>();
+ }
+ VisibilityAttr *Attr = ::new (Context) VisibilityAttr(Range, Context, Vis);
+ if (Inherited)
+ Attr->setInherited(true);
+ D->addAttr(Attr);
+ return true;
}
static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- // Find the last Decl that has an attribute.
- VisibilityAttr *PrevAttr = 0;
- assert(D->redecls_begin() == D);
- for (Decl::redecl_iterator I = D->redecls_begin(), E = D->redecls_end();
- I != E; ++I) {
- PrevAttr = I->getAttr<VisibilityAttr>() ;
- if (PrevAttr)
- break;
- }
-
- if (PrevAttr) {
- VisibilityAttr::VisibilityType PrevVisibility = PrevAttr->getVisibility();
- if (PrevVisibility != type) {
- S.Diag(Attr.getLoc(), diag::err_mismatched_visibility);
- S.Diag(PrevAttr->getLocation(), diag::note_previous_attribute);
- return;
- }
- }
- D->addAttr(::new (S.Context) VisibilityAttr(Attr.getRange(), S.Context, type));
+ S.mergeVisibilityAttr(D, Attr.getRange(), false, type);
}
static void handleObjCMethodFamilyAttr(Sema &S, Decl *decl,
bool NonInheritable, bool Inheritable) {
SmallVector<const AttributeList*, 4> attrs;
for (const AttributeList* l = AttrList; l; l = l->getNext()) {
+ ProcessDeclAttribute(*this, S, D, *l, NonInheritable, Inheritable);
attrs.push_back(l);
}
- for (int i = attrs.size() - 1; i >= 0; --i) {
- ProcessDeclAttribute(*this, S, D, *attrs[i], NonInheritable, Inheritable);
- }
// GCC accepts
// static int a9 __attribute__((weakref));
S.Context));
}
+bool Sema::mergeDLLImportAttr(Decl *D, SourceRange Range, bool Inherited) {
+ if (D->hasAttr<DLLExportAttr>()) {
+ Diag(Range.getBegin(), diag::warn_attribute_ignored) << "dllimport";
+ return false;
+ }
+
+ if (D->hasAttr<DLLImportAttr>())
+ return false;
+
+ DLLImportAttr *Attr =
+ ::new (Context) DLLImportAttr(Range, Context);
+ if (Inherited)
+ Attr->setInherited(true);
+ D->addAttr(Attr);
+
+ return true;
+}
+
static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
// check the attribute arguments.
if (Attr.getNumArgs() != 0) {
}
// Attribute can be applied only to functions or variables.
- if (isa<VarDecl>(D)) {
- D->addAttr(::new (S.Context) DLLImportAttr(Attr.getLoc(), S.Context));
- return;
- }
-
FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
- if (!FD) {
+ if (!FD && !isa<VarDecl>(D)) {
// Apparently Visual C++ thinks it is okay to not emit a warning
// in this case, so only emit a warning when -fms-extensions is not
// specified.
// Currently, the dllimport attribute is ignored for inlined functions.
// Warning is emitted.
- if (FD->isInlineSpecified()) {
+ if (FD && FD->isInlineSpecified()) {
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
return;
}
- if (D->getAttr<DLLExportAttr>()) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
- return;
+ S.mergeDLLImportAttr(D, Attr.getRange(), false);
+}
+
+bool Sema::mergeDLLExportAttr(Decl *D, SourceRange Range, bool Inherited) {
+ if (DLLImportAttr *Import = D->getAttr<DLLImportAttr>()) {
+ Diag(Import->getLocation(), diag::warn_attribute_ignored) << "dllimport";
+ D->dropAttr<DLLImportAttr>();
}
- D->addAttr(::new (S.Context) DLLImportAttr(Attr.getLoc(), S.Context));
+ if (D->hasAttr<DLLExportAttr>())
+ return false;
+
+ DLLExportAttr *Attr =
+ ::new (Context) DLLExportAttr(Range, Context);
+ if (Inherited)
+ Attr->setInherited(true);
+ D->addAttr(Attr);
+
+ return true;
}
static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
}
// Attribute can be applied only to functions or variables.
- if (isa<VarDecl>(D)) {
- D->addAttr(::new (S.Context) DLLExportAttr(Attr.getLoc(), S.Context));
- return;
- }
-
FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
- if (!FD) {
+ if (!FD && !isa<VarDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << 2 /*variable and function*/;
return;
// Currently, the dllexport attribute is ignored for inlined functions, unless
// the -fkeep-inline-functions flag has been used. Warning is emitted;
- if (FD->isInlineSpecified()) {
+ if (FD && FD->isInlineSpecified()) {
// FIXME: ... unless the -fkeep-inline-functions flag has been used.
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllexport";
return;
}
- if (DLLImportAttr *Import = D->getAttr<DLLImportAttr>()) {
- S.Diag(Import->getLocation(), diag::warn_attribute_ignored) << "dllimport";
- D->dropAttr<DLLImportAttr>();
- }
-
- D->addAttr(::new (S.Context) DLLExportAttr(Attr.getLoc(), S.Context));
+ S.mergeDLLExportAttr(D, Attr.getRange(), false);
}
namespace {