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.
}];
}
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">;
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").
// 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.
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.
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))
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}}