]> granicus.if.org Git - clang/commitdiff
Warn when attribute 'optnone' conflicts with attributes on a
authorPaul Robinson <paul_robinson@playstation.sony.com>
Mon, 15 Dec 2014 18:57:28 +0000 (18:57 +0000)
committerPaul Robinson <paul_robinson@playstation.sony.com>
Mon, 15 Dec 2014 18:57:28 +0000 (18:57 +0000)
different declaration of the same function.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@224256 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/AttrDocs.td
include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Sema/Sema.h
lib/CodeGen/CodeGenModule.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclAttr.cpp
test/SemaCXX/attr-optnone.cpp

index 13b2b7e06ace81443306347575614c7be46cc1b5..918abb6072ea11e905f5f725fc3fee1fb3337fa1 100644 (file)
@@ -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.
   }];
 }
 
index 32bf1b067b7b60caec889db792f791fd2405d7f3..22f66bda746bbd1b1ec72a22388475f5743d58df 100644 (file)
@@ -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">;
index 02aa984da5608d02ff5720a823f7a2e03e13d851..b0d9be449a4d3d9ccfe77d5250d21f5c8295fb37 100644 (file)
@@ -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").
index 06467fda6ef866d4f012b670768babfd7ce56430..87bd955a6c036f0af4b859ed47a8c89c0bb4fa95 100644 (file)
@@ -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.
index f75a2cee63c5fc93427c7dd1f1871b3086e36c75..0d33deaa5e590b2056b70e6b96eb693ca455bb68 100644 (file)
@@ -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.
index 6cc79fff3eac3adda58b92592e3996a254bf5bcc..6248f6c78befabcededbf2c7b86be194bd716aa8 100644 (file)
@@ -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))
index e2fce8e239425b2d5c2ce8bf289e47e7378e35ec..89ef6c579537a1615c2ce302bbd3b99b5ce9c5fa 100644 (file)
@@ -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}}