Warn when attribute 'optnone' conflicts with attributes on a

different declaration of the same function.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@224256 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Paul Robinson 2014-12-15 18:57:28 +00:00
Родитель 1a820646d2
Коммит eefcef89c7
7 изменённых файлов: 86 добавлений и 4 удалений

Просмотреть файл

@ -1264,7 +1264,8 @@ entire application without optimization. Avoiding optimization on the
specified function can improve the quality of the debugging information
for that function.
This attribute is incompatible with the ``always_inline`` attribute.
This attribute is incompatible with the ``always_inline`` and ``minsize``
attributes.
}];
}

Просмотреть файл

@ -2608,6 +2608,7 @@ def warn_attribute_protected_visibility :
InGroup<DiagGroup<"unsupported-visibility">>;
def err_mismatched_visibility: Error<"visibility does not match previous declaration">;
def note_previous_attribute : Note<"previous attribute is here">;
def note_conflicting_attribute : Note<"conflicting attribute is here">;
def note_attribute : Note<"attribute is here">;
def err_mismatched_ms_inheritance : Error<
"inheritance model does not match %select{definition|previous declaration}0">;

Просмотреть файл

@ -2005,6 +2005,12 @@ public:
int FirstArg, unsigned AttrSpellingListIndex);
SectionAttr *mergeSectionAttr(Decl *D, SourceRange Range, StringRef Name,
unsigned AttrSpellingListIndex);
AlwaysInlineAttr *mergeAlwaysInlineAttr(Decl *D, SourceRange Range,
unsigned AttrSpellingListIndex);
MinSizeAttr *mergeMinSizeAttr(Decl *D, SourceRange Range,
unsigned AttrSpellingListIndex);
OptimizeNoneAttr *mergeOptimizeNoneAttr(Decl *D, SourceRange Range,
unsigned AttrSpellingListIndex);
/// \brief Describes the kind of merge to perform for availability
/// attributes (including "deprecated", "unavailable", and "availability").

Просмотреть файл

@ -769,9 +769,10 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
// OptimizeNone wins over OptimizeForSize, MinSize, AlwaysInline.
assert(!F->hasFnAttribute(llvm::Attribute::OptimizeForSize) &&
"OptimizeNone and OptimizeForSize on same function!");
// FIXME: Change these to asserts.
F->removeFnAttr(llvm::Attribute::MinSize);
F->removeFnAttr(llvm::Attribute::AlwaysInline);
assert(!F->hasFnAttribute(llvm::Attribute::MinSize) &&
"OptimizeNone and MinSize on same function!");
assert(!F->hasFnAttribute(llvm::Attribute::AlwaysInline) &&
"OptimizeNone and AlwaysInline on same function!");
// Attribute 'inlinehint' has no effect on 'optnone' functions.
// Explicitly remove it from the set of function attributes.

Просмотреть файл

@ -2154,6 +2154,12 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
NewAttr = S.mergeMSInheritanceAttr(D, IA->getRange(), IA->getBestCase(),
AttrSpellingListIndex,
IA->getSemanticSpelling());
else if (const auto *AA = dyn_cast<AlwaysInlineAttr>(Attr))
NewAttr = S.mergeAlwaysInlineAttr(D, AA->getRange(), AttrSpellingListIndex);
else if (const auto *MA = dyn_cast<MinSizeAttr>(Attr))
NewAttr = S.mergeMinSizeAttr(D, MA->getRange(), AttrSpellingListIndex);
else if (const auto *OA = dyn_cast<OptimizeNoneAttr>(Attr))
NewAttr = S.mergeOptimizeNoneAttr(D, OA->getRange(), AttrSpellingListIndex);
else if (isa<AlignedAttr>(Attr))
// AlignedAttrs are handled separately, because we need to handle all
// such attributes on a declaration at the same time.

Просмотреть файл

@ -3136,6 +3136,55 @@ static void handleNoDebugAttr(Sema &S, Decl *D, const AttributeList &Attr) {
Attr.getAttributeSpellingListIndex()));
}
AlwaysInlineAttr *Sema::mergeAlwaysInlineAttr(Decl *D, SourceRange Range,
unsigned AttrSpellingListIndex) {
if (OptimizeNoneAttr *Optnone = D->getAttr<OptimizeNoneAttr>()) {
Diag(Range.getBegin(), diag::warn_attribute_ignored) << "'always_inline'";
Diag(Optnone->getLocation(), diag::note_conflicting_attribute);
return nullptr;
}
if (D->hasAttr<AlwaysInlineAttr>())
return nullptr;
return ::new (Context) AlwaysInlineAttr(Range, Context,
AttrSpellingListIndex);
}
MinSizeAttr *Sema::mergeMinSizeAttr(Decl *D, SourceRange Range,
unsigned AttrSpellingListIndex) {
if (OptimizeNoneAttr *Optnone = D->getAttr<OptimizeNoneAttr>()) {
Diag(Range.getBegin(), diag::warn_attribute_ignored) << "'minsize'";
Diag(Optnone->getLocation(), diag::note_conflicting_attribute);
return nullptr;
}
if (D->hasAttr<MinSizeAttr>())
return nullptr;
return ::new (Context) MinSizeAttr(Range, Context, AttrSpellingListIndex);
}
OptimizeNoneAttr *Sema::mergeOptimizeNoneAttr(Decl *D, SourceRange Range,
unsigned AttrSpellingListIndex) {
if (AlwaysInlineAttr *Inline = D->getAttr<AlwaysInlineAttr>()) {
Diag(Inline->getLocation(), diag::warn_attribute_ignored) << Inline;
Diag(Range.getBegin(), diag::note_conflicting_attribute);
D->dropAttr<AlwaysInlineAttr>();
}
if (MinSizeAttr *MinSize = D->getAttr<MinSizeAttr>()) {
Diag(MinSize->getLocation(), diag::warn_attribute_ignored) << MinSize;
Diag(Range.getBegin(), diag::note_conflicting_attribute);
D->dropAttr<MinSizeAttr>();
}
if (D->hasAttr<OptimizeNoneAttr>())
return nullptr;
return ::new (Context) OptimizeNoneAttr(Range, Context,
AttrSpellingListIndex);
}
static void handleAlwaysInlineAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
if (checkAttrMutualExclusion<OptimizeNoneAttr>(S, D, Attr))

Просмотреть файл

@ -6,9 +6,27 @@ int bar() __attribute__((optnone)) __attribute__((noinline));
int baz() __attribute__((always_inline)) __attribute__((optnone)); // expected-error{{'always_inline' and 'optnone' attributes are not compatible}}
int quz() __attribute__((optnone)) __attribute__((always_inline)); // expected-error{{'optnone' and 'always_inline' attributes are not compatible}}
__attribute__((always_inline)) int baz1(); // expected-warning{{'always_inline' attribute ignored}}
__attribute__((optnone)) int baz1() { return 1; } // expected-note{{conflicting attribute is here}}
__attribute__((optnone)) int quz1(); // expected-note{{conflicting attribute is here}}
__attribute__((always_inline)) int quz1() { return 1; } // expected-warning{{'always_inline' attribute ignored}}
int bay() __attribute__((minsize)) __attribute__((optnone)); // expected-error{{'minsize' and 'optnone' attributes are not compatible}}
int quy() __attribute__((optnone)) __attribute__((minsize)); // expected-error{{'optnone' and 'minsize' attributes are not compatible}}
__attribute__((minsize)) int bay1(); // expected-warning{{'minsize' attribute ignored}}
__attribute__((optnone)) int bay1() { return 1; } // expected-note{{conflicting attribute is here}}
__attribute__((optnone)) int quy1(); // expected-note{{conflicting attribute is here}}
__attribute__((minsize)) int quy1() { return 1; } // expected-warning{{'minsize' attribute ignored}}
__attribute__((always_inline)) // expected-warning{{'always_inline' attribute ignored}}
__attribute__((minsize)) // expected-warning{{'minsize' attribute ignored}}
void bay2();
__attribute__((optnone)) // expected-note 2 {{conflicting}}
void bay2() {}
__forceinline __attribute__((optnone)) int bax(); // expected-error{{'__forceinline' and 'optnone' attributes are not compatible}}
__attribute__((optnone)) __forceinline int qux(); // expected-error{{'optnone' and '__forceinline' attributes are not compatible}}