зеркало из https://github.com/microsoft/clang.git
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:
Родитель
1a820646d2
Коммит
eefcef89c7
|
@ -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}}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче