[PATCH] Downgrade 'optnone' attribute conflicts to warning

Aaron Ballman aaron.ballman at gmail.com
Tue Jan 13 06:55:03 PST 2015


On Mon, Jan 12, 2015 at 3:31 PM, Paul Robinson
<Paul_Robinson at playstation.sony.com> wrote:
> Hi aaron.ballman,
>
> When attribute 'optnone' appears on the same declaration with a
> conflicting attribute, warn about the conflict and pick a "winning"
> attribute to preserve, instead of emitting an error.  This matches the
> behavior when the conflicting attributes are on different declarations.
>
> Along the way I discovered that conflicts involving __forceinline were
> reported as 'always_inline' (alternate spellings for the same
> attribute) so I hacked in a way to provide the spelling used in the
> declaration. There must be a better way, though...

LGTM, with one possible suggestion below.

>
> http://reviews.llvm.org/D6933
>
> Files:
>   include/clang/Sema/Sema.h
>   lib/Sema/SemaDecl.cpp
>   lib/Sema/SemaDeclAttr.cpp
>   test/SemaCXX/attr-optnone.cpp
>
> EMAIL PREFERENCES
>   http://reviews.llvm.org/settings/panel/emailpreferences/

> Index: include/clang/Sema/Sema.h
> ===================================================================
> --- include/clang/Sema/Sema.h
> +++ include/clang/Sema/Sema.h
> @@ -2009,6 +2009,7 @@
>    SectionAttr *mergeSectionAttr(Decl *D, SourceRange Range, StringRef Name,
>                                  unsigned AttrSpellingListIndex);
>    AlwaysInlineAttr *mergeAlwaysInlineAttr(Decl *D, SourceRange Range,
> +                                          StringRef Name,
>                                            unsigned AttrSpellingListIndex);
>    MinSizeAttr *mergeMinSizeAttr(Decl *D, SourceRange Range,
>                                  unsigned AttrSpellingListIndex);
> Index: lib/Sema/SemaDecl.cpp
> ===================================================================
> --- lib/Sema/SemaDecl.cpp
> +++ lib/Sema/SemaDecl.cpp
> @@ -2155,7 +2155,8 @@
>                                         AttrSpellingListIndex,
>                                         IA->getSemanticSpelling());
>    else if (const auto *AA = dyn_cast<AlwaysInlineAttr>(Attr))
> -    NewAttr = S.mergeAlwaysInlineAttr(D, AA->getRange(), AttrSpellingListIndex);
> +    NewAttr = S.mergeAlwaysInlineAttr(D, AA->getRange(), AA->getSpelling(),
> +                                      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))
> Index: lib/Sema/SemaDeclAttr.cpp
> ===================================================================
> --- lib/Sema/SemaDeclAttr.cpp
> +++ lib/Sema/SemaDeclAttr.cpp
> @@ -3141,9 +3141,14 @@
>  }
>
>  AlwaysInlineAttr *Sema::mergeAlwaysInlineAttr(Decl *D, SourceRange Range,
> +                                              StringRef Name,
>                                                unsigned AttrSpellingListIndex) {
>    if (OptimizeNoneAttr *Optnone = D->getAttr<OptimizeNoneAttr>()) {
> -    Diag(Range.getBegin(), diag::warn_attribute_ignored) << "'always_inline'";
> +    SmallString<40> QuotedName;
> +    QuotedName = "'";
> +    QuotedName += Name;
> +    QuotedName += "'";
> +    Diag(Range.getBegin(), diag::warn_attribute_ignored) << QuotedName;
>      Diag(Optnone->getLocation(), diag::note_conflicting_attribute);
>      return nullptr;
>    }

You could pass in the name as an IdentifierInfo * and ditch the manual
quoting. I realize that Attr::getSpelling() returns a StringRef, but
getting the IdentifierInfo should be low-cost and slightly less ugly.


> @@ -3191,34 +3196,23 @@
>
>  static void handleAlwaysInlineAttr(Sema &S, Decl *D,
>                                     const AttributeList &Attr) {
> -  if (checkAttrMutualExclusion<OptimizeNoneAttr>(S, D, Attr))
> -    return;
> -
> -  D->addAttr(::new (S.Context)
> -             AlwaysInlineAttr(Attr.getRange(), S.Context,
> -                              Attr.getAttributeSpellingListIndex()));
> +  if (AlwaysInlineAttr *Inline = S.mergeAlwaysInlineAttr(
> +          D, Attr.getRange(), Attr.getName()->getName(),
> +          Attr.getAttributeSpellingListIndex()))
> +    D->addAttr(Inline);
>  }
>
> -static void handleMinSizeAttr(Sema &S, Decl *D,
> -                              const AttributeList &Attr) {
> -  if (checkAttrMutualExclusion<OptimizeNoneAttr>(S, D, Attr))
> -    return;
> -
> -  D->addAttr(::new (S.Context)
> -             MinSizeAttr(Attr.getRange(), S.Context,
> -                         Attr.getAttributeSpellingListIndex()));
> +static void handleMinSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
> +  if (MinSizeAttr *MinSize = S.mergeMinSizeAttr(
> +          D, Attr.getRange(), Attr.getAttributeSpellingListIndex()))
> +    D->addAttr(MinSize);
>  }
>
>  static void handleOptimizeNoneAttr(Sema &S, Decl *D,
>                                     const AttributeList &Attr) {
> -  if (checkAttrMutualExclusion<AlwaysInlineAttr>(S, D, Attr))
> -    return;
> -  if (checkAttrMutualExclusion<MinSizeAttr>(S, D, Attr))
> -    return;
> -
> -  D->addAttr(::new (S.Context)
> -             OptimizeNoneAttr(Attr.getRange(), S.Context,
> -                              Attr.getAttributeSpellingListIndex()));
> +  if (OptimizeNoneAttr *Optnone = S.mergeOptimizeNoneAttr(
> +          D, Attr.getRange(), Attr.getAttributeSpellingListIndex()))
> +    D->addAttr(Optnone);
>  }
>
>  static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) {
> Index: test/SemaCXX/attr-optnone.cpp
> ===================================================================
> --- test/SemaCXX/attr-optnone.cpp
> +++ test/SemaCXX/attr-optnone.cpp
> @@ -3,17 +3,17 @@
>  int foo() __attribute__((optnone));
>  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}}
> +int baz() __attribute__((always_inline)) __attribute__((optnone)); // expected-warning{{'always_inline' attribute ignored}} expected-note{{conflicting attribute is here}}
> +int quz() __attribute__((optnone)) __attribute__((always_inline)); // expected-warning{{'always_inline' attribute ignored}} expected-note{{conflicting attribute is here}}
>
>  __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}}
> +int bay() __attribute__((minsize)) __attribute__((optnone)); // expected-warning{{'minsize' attribute ignored}} expected-note{{conflicting}}
> +int quy() __attribute__((optnone)) __attribute__((minsize)); // expected-warning{{'minsize' attribute ignored}} expected-note{{conflicting}}
>
>  __attribute__((minsize)) int bay1(); // expected-warning{{'minsize' attribute ignored}}
>  __attribute__((optnone)) int bay1() { return 1; } // expected-note{{conflicting attribute is here}}
> @@ -27,8 +27,13 @@
>  __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}}
> +__forceinline __attribute__((optnone)) int bax(); // expected-warning{{'__forceinline' attribute ignored}} expected-note{{conflicting}}
> +__attribute__((optnone)) __forceinline int qux(); // expected-warning{{'__forceinline' attribute ignored}} expected-note{{conflicting}}
> +
> +__forceinline int bax2(); // expected-warning{{'__forceinline' attribute ignored}}
> +__attribute__((optnone)) int bax2() { return 1; } // expected-note{{conflicting}}
> +__attribute__((optnone)) int qux2(); // expected-note{{conflicting}}
> +__forceinline int qux2() { return 1; } // expected-warning{{'__forceinline' attribute ignored}}
>
>  int globalVar __attribute__((optnone)); // expected-warning{{'optnone' attribute only applies to functions}}
>
> @@ -50,8 +55,8 @@
>  [[clang::optnone]]
>  int bar2() __attribute__((noinline));
>
> -[[clang::optnone]]
> -int baz2() __attribute__((always_inline)); // expected-error{{'always_inline' and 'optnone' attributes are not compatible}}
> +[[clang::optnone]] // expected-note {{conflicting}}
> +int baz2() __attribute__((always_inline)); // expected-warning{{'always_inline' attribute ignored}}
>
>  [[clang::optnone]] int globalVar2; //expected-warning{{'optnone' attribute only applies to functions}}
>
>

~Aaron



More information about the cfe-commits mailing list