nickdesaulniers added inline comments.

================
Comment at: clang/include/clang/Basic/DiagnosticSemaKinds.td:11172
 
+def err_attribute_removed_on_redeclaration : Error<
+  "'%0' attribute removed from redeclared variable">;
----------------
aaron.ballman wrote:
> This diagnostic is a bit confusing to me -- should this be a warning about 
> the attribute being ignored in this case, rather than an error? 
> Alternatively, should this be re-worded to say that the attribute must appear 
> on the first declaration? If the latter, we have some diagnostics that could 
> maybe be combined into using a `%select` for this: 
> `err_noreturn_missing_on_first_decl` and `err_internal_linkage_redeclaration` 
> are awfully similar to the same thing.
Rebased onto D107613; reusing `diag::err_attribute_missing_on_first_decl` now. 
done.


================
Comment at: clang/lib/Sema/SemaDecl.cpp:2982
 
+  // If redeclaration removes error or warning attribute...
+  if (auto *EA = New->getAttr<ErrorAttr>())
----------------
aaron.ballman wrote:
> The comment doesn't seem to match the code -- this is when the redeclaration 
> *adds* the attribute. And don't we want to silently accept that if the 
> redeclaration adds the same annotation with the same message? e.g.,
> ```
> __attribute__((error("derp"))) void func();
> __attribute__((error("derp"))) void func(); // fine
> __attribute__((error("derp"))) void func() {} // fine
> ```
Rebased onto D107613, so this block was moved from `Sema::mergeDeclAttributes` 
(which should be for `Attributes` on any subclass of `Decl`, which is too 
generic for a `FunctionDecl` only `Attribute`) to `Sema::MergeFunctionDecl` 
(which is only for `FunctionDecl` `Attribute`s).

I had a similar test case already in clang/test/Sema/attr-error.c testing 
`__attribute__((error("foo"), error("foo"))) int good1(void);`, but I will add 
a test to that file for redeclarations with matching attributes. done.


================
Comment at: clang/lib/Sema/SemaDeclAttr.cpp:955
+
+  if (const auto *EA = D->getAttr<ErrorAttr>()) {
+    unsigned NewAttrSpellingIndex = AL.getAttributeSpellingListIndex();
----------------
aaron.ballman wrote:
> This logic will catch the case where the attributes are processed in a group 
> (e.g., two attributes in one specifier or two attributes on the same 
> declaration) but it won't handle the redeclaration merging case. I think you 
> need to follow the attribute merge pattern used in SemaDecl.cpp.
I'm not sure that I need to change anything here; redeclarations of 
`ErrorAttr`s are checked in `Sema::MergeFunctionDecl`.

But when I was playing around with something else here earlier this week, I 
noticed a pre-existing inconsistency (or maybe just a difference, described 
below) of `handle*Attr` functionns vs `merge*Attr` functions.

`mergeDeclAttribute` in `clang/lib/Sema/SemaDecl.cpp` has a large `if`/`else` 
chain for new attrs, which calls `merge*Attr` methods of `Sema`, but it doesn't 
give your a reference to any "`Old`"/pre-existing attr that may be in conflict. 
 A comment in `mergeDeclAttribute` seems to confirm this.

>> // This function copies an attribute Attr from a previous declaration to the 
>>                                                                              
>>               
>> // new declaration D if the new declaration doesn't itself have that 
>> attribute                                                                    
>>                       
>> // yet or if that attribute allows duplicates.

Because we do not allow this `Attribute` to be added on subsequent `Decl`s, I 
_do not think_ we need to follow the attribute merge pattern used in 
SemaDecl.cpp.  But I could be wrong; please triple check.


================
Comment at: clang/lib/Sema/SemaDeclAttr.cpp:964-965
+    bool match =
+        (EA->isError() && NewAttrSpellingIndex < ErrorAttr::GNU_warning) ||
+        (EA->isWarning() && NewAttrSpellingIndex >= ErrorAttr::GNU_warning);
+    if (!match) {
----------------
aaron.ballman wrote:
> It's a bit tricky for me to tell from the patch -- are the enumerators in the 
> correct order that this logic still works for when the [[]] spelling is used?
For reference, the generated `enum Spelling` looks like:
```
 3611 public:                                                                   
                                                                                
                
 3612   enum Spelling {                                                         
                                                                                
                
 3613     GNU_error = 0,                                                        
                                                                                
                
 3614     CXX11_gnu_error = 1,                                                  
                                                                                
                
 3615     C2x_gnu_error = 2,                                                    
                                                                                
                
 3616     GNU_warning = 3,                                                      
                                                                                
                
 3617     CXX11_gnu_warning = 4,                                                
                                                                                
                
 3618     C2x_gnu_warning = 5,                                                  
                                                                                
                
 3619   SpellingNotCalculated = 15                                              
                                                                                
                
 3620                                                                           
                                                                                
                
 3621   };
```
while using `getAttributeSpellingListIndex` rather than `getNormalizedFullName` 
allows us to avoid a pair of string comparisons in favor of a pair of 
`unsigned` comparisons, we now have an issue because there are technically six 
spellings. (I guess it's not clear to me what's `CXX11_gnu_*` vs `C2x_gnu_*`?)  
We could be explicit against checking all six rather than two comparisons.

Or I can use local variables with more helpful identifiers like:

```
bool NewAttrIsError = NewAttrSpellingIndex < ErrorAttr::GNU_warning;
bool NewAttrIsWarning = NewAttrSpellingIndex >= ErrorAttr::GNU_warning;
bool Match = (EA->isError() && NewAttrIsError) || (EA->isWarning() && 
NewAttrIsWarning);
```

WDYT?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D106030/new/

https://reviews.llvm.org/D106030

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to