Thank you both for the input!

On Wed, Feb 23, 2011 at 6:00 PM, Douglas Gregor <[email protected]> wrote:
>
> On Feb 23, 2011, at 9:23 AM, Chandler Carruth wrote:
>
>> One overall concern I would have is that a parser struct is quadrupling in 
>> size. Can you measure the peak memory usage impact of this change on a hefty 
>> compilation?
>
> It shouldn't have any effect whatsoever, since PointerTypeInfo is only used 
> when it's in a union with the much-larger FunctionTypeInfo.
Great, I won't worry about that then.

>> Some nits below...
>>
>> Index: test/SemaCXX/return.cpp
>> ===================================================================
>> --- test/SemaCXX/return.cpp   (revision 126218)
>> +++ test/SemaCXX/return.cpp   (working copy)
>> @@ -24,5 +24,14 @@
>>  const volatile S class_cv();
>>
>>  const int scalar_c(); // expected-warning{{'const' type qualifier on return 
>> type has no effect}}
>> +
>> +const
>> +char*
>> +const // expected-warning{{'const' type qualifier on return type has no 
>> effect}}
>> +f();
>>
>> It would be good to test "T const" and "T const * const" as well for 
>> completeness...
Adding that.

>>
>> Index: include/clang/Sema/DeclSpec.h
>> ===================================================================
>> --- include/clang/Sema/DeclSpec.h     (revision 126218)
>> +++ include/clang/Sema/DeclSpec.h     (working copy)
>> @@ -825,6 +825,25 @@
>>    struct PointerTypeInfo : TypeInfoCommon {
>>      /// The type qualifiers: const/volatile/restrict.
>>      unsigned TypeQuals : 3;
>> +
>> +    /// The location of the const-qualifier, if any.
>> +    unsigned ConstQualLoc;
>> +
>> +    /// The location of the volatile-qualifier, if any.
>> +    unsigned VolatileQualLoc;
>> +
>> +    /// The location of the restrict-qualifier, if any.
>> +    unsigned RestrictQualLoc;
>> +
>> +    SourceLocation constQualLoc() const {
>> +      return SourceLocation::getFromRawEncoding(ConstQualLoc);
>> +    }
>> +    SourceLocation volatileQualLoc() const {
>> +      return SourceLocation::getFromRawEncoding(VolatileQualLoc);
>> +    }
>> +    SourceLocation restrictQualLoc() const {
>> +      return SourceLocation::getFromRawEncoding(RestrictQualLoc);
>> +    }
>>
>> I find the getters here a bit odd. As these are only accessed on one place, 
>> I wonder if we should do the raw encoding -> SourceLocation transition there.
You're right. I'll remove the getters.

>>
>> Perhaps most odd to me is that the members are public and doxymented, but 
>> they have non-trivial getters and those aren't doxymented. If you want 
>> getters on this struct, I'd make the members private and move the comments.
>>
>> Index: lib/Sema/SemaType.cpp
>> ===================================================================
>> --- lib/Sema/SemaType.cpp     (revision 126218)
>> +++ lib/Sema/SemaType.cpp     (working copy)
>> @@ -1395,6 +1395,49 @@
>>    return QT;
>>  }
>>
>> +static void DiagnoseIgnoredQualifiers(unsigned Quals,
>> +                                      SourceLocation constQualLoc,
>> +                                      SourceLocation volatileQualLoc,
>> +                                      SourceLocation restrictQualLoc,
>> +                                      Sema& S) {
>> +  std::string QualStr;
>> +  unsigned NumQuals = 0;
>> +  SourceLocation Loc;
>> +
>> +  if (Quals & Qualifiers::Const) {
>> +    Loc = constQualLoc;
>> +    ++NumQuals;
>> +    QualStr = "const";
>> +  }
>> +  if (Quals & Qualifiers::Volatile) {
>> +    if (NumQuals == 0) {
>> +      Loc = volatileQualLoc;
>> +      QualStr = "volatile";
>> +    } else
>> +      QualStr += " volatile";
>>
>> I think this section is moved verbatim, but while we're here, can we have 
>> {}s around this else block? Especially followed by a preincrement, I had to 
>> read in 3 times...
Done.

>>
>> +    ++NumQuals;
>> +  }
>> +  if (Quals & Qualifiers::Restrict) {
>> +    if (NumQuals == 0) {
>> +      Loc = restrictQualLoc;
>> +      QualStr = "restrict";
>> +    } else
>> +      QualStr += " restrict";
>>
>> Same here.
Done.

>>
>> +    ++NumQuals;
>> +  }
>> +
>> +  assert(NumQuals > 0 && "No known qualifiers?");
>> +  Sema::SemaDiagnosticBuilder DB = S.Diag(Loc, diag::warn_qual_return_type);
>> +
>> +  DB << QualStr << NumQuals;
>> +  if (Quals & Qualifiers::Const)
>> +    DB << FixItHint::CreateRemoval(constQualLoc);
>> +  if (Quals & Qualifiers::Volatile)
>> +    DB << FixItHint::CreateRemoval(volatileQualLoc);
>> +  if (Quals & Qualifiers::Restrict)
>> +    DB << FixItHint::CreateRemoval(restrictQualLoc);
>>
>> And I think we simplify this by having three empty FixItHint variable, and 
>> initializing them in each branch where we do the original checking. That 
>> should also avoid the need to store the diagnostic builder, and we can just 
>> stream the lot of this in directly.
Ah, yes that makes it nicer.


Attaching new patch addressing Chandler's comments.
Index: test/Sema/return.c
===================================================================
--- test/Sema/return.c	(revision 126218)
+++ test/Sema/return.c	(working copy)
@@ -242,6 +242,7 @@
 // Test warnings on ignored qualifiers on return types.
 const int ignored_c_quals(); // expected-warning{{'const' type qualifier on return type has no effect}}
 const volatile int ignored_cv_quals(); // expected-warning{{'const volatile' type qualifiers on return type have no effect}}
+char* const volatile restrict ignored_cvr_quals(); // expected-warning{{'const volatile restrict' type qualifiers on return type have no effect}}
 
 // Test that for switch(enum) that if the switch statement covers all the cases
 // that we don't consider that for -Wreturn-type.
@@ -254,4 +255,3 @@
   case C3: return 4;
   }
 } // no-warning
-
Index: test/SemaCXX/return.cpp
===================================================================
--- test/SemaCXX/return.cpp	(revision 126218)
+++ test/SemaCXX/return.cpp	(working copy)
@@ -24,5 +24,20 @@
 const volatile S class_cv();
 
 const int scalar_c(); // expected-warning{{'const' type qualifier on return type has no effect}}
+int const scalar_c2(); // expected-warning{{'const' type qualifier on return type has no effect}}
+
+const
+char*
+const // expected-warning{{'const' type qualifier on return type has no effect}}
+f();
+
+char
+const*
+const // expected-warning{{'const' type qualifier on return type has no effect}}
+g();
+
+char* const h(); // expected-warning{{'const' type qualifier on return type has no effect}}
+char* volatile i(); // expected-warning{{'volatile' type qualifier on return type has no effect}}
+
 const volatile int scalar_cv(); // expected-warning{{'const volatile' type qualifiers on return type have no effect}}
 }
Index: include/clang/Sema/DeclSpec.h
===================================================================
--- include/clang/Sema/DeclSpec.h	(revision 126218)
+++ include/clang/Sema/DeclSpec.h	(working copy)
@@ -825,6 +825,16 @@
   struct PointerTypeInfo : TypeInfoCommon {
     /// The type qualifiers: const/volatile/restrict.
     unsigned TypeQuals : 3;
+
+    /// The location of the const-qualifier, if any.
+    unsigned ConstQualLoc;
+
+    /// The location of the volatile-qualifier, if any.
+    unsigned VolatileQualLoc;
+
+    /// The location of the restrict-qualifier, if any.
+    unsigned RestrictQualLoc;
+
     void destroy() {
     }
   };
@@ -1055,12 +1065,18 @@
   /// getPointer - Return a DeclaratorChunk for a pointer.
   ///
   static DeclaratorChunk getPointer(unsigned TypeQuals, SourceLocation Loc,
+                                    SourceLocation ConstQualLoc,
+                                    SourceLocation VolatileQualLoc,
+                                    SourceLocation RestrictQualLoc,
                                     const ParsedAttributes &attrs) {
     DeclaratorChunk I;
-    I.Kind          = Pointer;
-    I.Loc           = Loc;
-    I.Ptr.TypeQuals = TypeQuals;
-    I.Ptr.AttrList  = attrs.getList();
+    I.Kind                = Pointer;
+    I.Loc                 = Loc;
+    I.Ptr.TypeQuals       = TypeQuals;
+    I.Ptr.ConstQualLoc    = ConstQualLoc.getRawEncoding();
+    I.Ptr.VolatileQualLoc = VolatileQualLoc.getRawEncoding();
+    I.Ptr.RestrictQualLoc = RestrictQualLoc.getRawEncoding();
+    I.Ptr.AttrList        = attrs.getList();
     return I;
   }
 
Index: lib/Sema/SemaType.cpp
===================================================================
--- lib/Sema/SemaType.cpp	(revision 126218)
+++ lib/Sema/SemaType.cpp	(working copy)
@@ -1395,6 +1395,54 @@
   return QT;
 }
 
+static void DiagnoseIgnoredQualifiers(unsigned Quals,
+                                      SourceLocation ConstQualLoc,
+                                      SourceLocation VolatileQualLoc,
+                                      SourceLocation RestrictQualLoc,
+                                      Sema& S) {
+  std::string QualStr;
+  unsigned NumQuals = 0;
+  SourceLocation Loc;
+
+  FixItHint ConstFixIt;
+  FixItHint VolatileFixIt;
+  FixItHint RestrictFixIt;
+
+  if (Quals & Qualifiers::Const) {
+    ConstFixIt = FixItHint::CreateRemoval(ConstQualLoc);
+    Loc = ConstQualLoc;
+    ++NumQuals;
+    QualStr = "const";
+  }
+  if (Quals & Qualifiers::Volatile) {
+    VolatileFixIt = FixItHint::CreateRemoval(VolatileQualLoc);
+    if (NumQuals == 0) {
+      Loc = VolatileQualLoc;
+      QualStr = "volatile";
+    } else {
+      QualStr += " volatile";
+    }
+    ++NumQuals;
+  }
+  if (Quals & Qualifiers::Restrict) {
+    RestrictFixIt = FixItHint::CreateRemoval(RestrictQualLoc);
+    if (NumQuals == 0) {
+      Loc = RestrictQualLoc;
+      QualStr = "restrict";
+    } else {
+      QualStr += " restrict";
+    }
+    ++NumQuals;
+  }
+
+  assert(NumQuals > 0 && "No known qualifiers?");
+
+  S.Diag(Loc, diag::warn_qual_return_type) << QualStr << NumQuals
+                                           << ConstFixIt
+                                           << VolatileFixIt
+                                           << RestrictFixIt;
+}
+
 /// GetTypeForDeclarator - Convert the type for the specified
 /// declarator to Type instances.
 ///
@@ -1678,46 +1726,31 @@
 
       // cv-qualifiers on return types are pointless except when the type is a
       // class type in C++.
-      if (T.getCVRQualifiers() && D.getDeclSpec().getTypeQualifiers() &&
+      if (T->isPointerType() && T.getCVRQualifiers() &&
+          (!getLangOptions().CPlusPlus || !T->isDependentType())) {
+        assert(chunkIndex + 1 < e && "No DeclaratorChunk for the return type?");
+        DeclaratorChunk ReturnTypeChunk = D.getTypeObject(chunkIndex + 1);
+        assert(ReturnTypeChunk.Kind == DeclaratorChunk::Pointer);
+
+        DeclaratorChunk::PointerTypeInfo &PTI = ReturnTypeChunk.Ptr;
+
+        DiagnoseIgnoredQualifiers(PTI.TypeQuals,
+            SourceLocation::getFromRawEncoding(PTI.ConstQualLoc),
+            SourceLocation::getFromRawEncoding(PTI.VolatileQualLoc),
+            SourceLocation::getFromRawEncoding(PTI.RestrictQualLoc),
+            *this);
+
+      } else if (T.getCVRQualifiers() && D.getDeclSpec().getTypeQualifiers() &&
           (!getLangOptions().CPlusPlus ||
            (!T->isDependentType() && !T->isRecordType()))) {
-        unsigned Quals = D.getDeclSpec().getTypeQualifiers();
-        std::string QualStr;
-        unsigned NumQuals = 0;
-        SourceLocation Loc;
-        if (Quals & Qualifiers::Const) {
-          Loc = D.getDeclSpec().getConstSpecLoc();
-          ++NumQuals;
-          QualStr = "const";
-        }
-        if (Quals & Qualifiers::Volatile) {
-          if (NumQuals == 0) {
-            Loc = D.getDeclSpec().getVolatileSpecLoc();
-            QualStr = "volatile";
-          } else
-            QualStr += " volatile";
-          ++NumQuals;
-        }
-        if (Quals & Qualifiers::Restrict) {
-          if (NumQuals == 0) {
-            Loc = D.getDeclSpec().getRestrictSpecLoc();
-            QualStr = "restrict";
-          } else
-            QualStr += " restrict";
-          ++NumQuals;
-        }
-        assert(NumQuals > 0 && "No known qualifiers?");
-            
-        SemaDiagnosticBuilder DB = Diag(Loc, diag::warn_qual_return_type);
-        DB << QualStr << NumQuals;
-        if (Quals & Qualifiers::Const)
-          DB << FixItHint::CreateRemoval(D.getDeclSpec().getConstSpecLoc());
-        if (Quals & Qualifiers::Volatile)
-          DB << FixItHint::CreateRemoval(D.getDeclSpec().getVolatileSpecLoc());
-        if (Quals & Qualifiers::Restrict)
-          DB << FixItHint::CreateRemoval(D.getDeclSpec().getRestrictSpecLoc());
+
+        DiagnoseIgnoredQualifiers(D.getDeclSpec().getTypeQualifiers(),
+                                  D.getDeclSpec().getConstSpecLoc(),
+                                  D.getDeclSpec().getVolatileSpecLoc(),
+                                  D.getDeclSpec().getRestrictSpecLoc(),
+                                  *this);
       }
-      
+
       if (getLangOptions().CPlusPlus && D.getDeclSpec().isTypeSpecOwned()) {
         // C++ [dcl.fct]p6:
         //   Types shall not be defined in return or parameter types.
Index: lib/Parse/ParseDecl.cpp
===================================================================
--- lib/Parse/ParseDecl.cpp	(revision 126218)
+++ lib/Parse/ParseDecl.cpp	(working copy)
@@ -2746,6 +2746,9 @@
     if (Kind == tok::star)
       // Remember that we parsed a pointer type, and remember the type-quals.
       D.AddTypeInfo(DeclaratorChunk::getPointer(DS.getTypeQualifiers(), Loc,
+                                                DS.getConstSpecLoc(),
+                                                DS.getVolatileSpecLoc(),
+                                                DS.getRestrictSpecLoc(),
                                                 DS.takeAttributes()),
                     SourceLocation());
     else
@@ -3742,4 +3745,3 @@
   }
   return false;
 }
-  
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to