diff options
author | Chandler Carruth <chandlerc@gmail.com> | 2011-02-23 18:51:59 +0000 |
---|---|---|
committer | Chandler Carruth <chandlerc@gmail.com> | 2011-02-23 18:51:59 +0000 |
commit | d067c07c6cbf099b25aba38bcb66f38e79d0c420 (patch) | |
tree | f1335f61d0db3ee2ab6e5251a96853ad8574eaa1 | |
parent | 87fb9404cd962b78c98947d75d68be1691c4e737 (diff) |
Fix the behavior of -Wignored-qualifiers on return type qualifiers in
several ways. We now warn for more of the return types, and correctly
locate the ignored ones. Also adds fix-it hints to remove the ignored
qualifiers. Fixes much of PR9058, although not all of it.
Patch by Hans Wennborg, a couple of minor style tweaks from me.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@126321 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Sema/DeclSpec.h | 24 | ||||
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 109 | ||||
-rw-r--r-- | test/Sema/return.c | 2 | ||||
-rw-r--r-- | test/SemaCXX/return.cpp | 15 |
5 files changed, 111 insertions, 43 deletions
diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index 9c4bb64694..abe84299f7 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -825,6 +825,16 @@ struct DeclaratorChunk { 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 @@ struct DeclaratorChunk { /// 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; } diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 5828bfa114..60c3a4c262 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -2762,6 +2762,9 @@ void Parser::ParseDeclaratorInternal(Declarator &D, 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 @@ -3758,4 +3761,3 @@ bool Parser::TryAltiVecTokenOutOfLine(DeclSpec &DS, SourceLocation Loc, } return false; } - diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 7c96a3f2de..d30ed74310 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -1395,6 +1395,56 @@ QualType Sema::GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo) { 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; + + // FIXME: The locations here are set kind of arbitrarily. It'd be nicer to + // find a range and grow it to encompass all the qualifiers, regardless of + // the order in which they textually appear. + 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 +1728,31 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, // 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. diff --git a/test/Sema/return.c b/test/Sema/return.c index 0c2c72ee53..d9456b6e35 100644 --- a/test/Sema/return.c +++ b/test/Sema/return.c @@ -242,6 +242,7 @@ static inline int si_forward() {} // expected-warning{{control reaches end of no // 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 @@ int test_enum_cases(enum Cases C) { case C3: return 4; } } // no-warning - diff --git a/test/SemaCXX/return.cpp b/test/SemaCXX/return.cpp index 441c20f152..46524fccfc 100644 --- a/test/SemaCXX/return.cpp +++ b/test/SemaCXX/return.cpp @@ -24,5 +24,20 @@ const S class_c(); 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}} } |