Improve the warning for cv-qualifiers on free functions, from Ahmed Charles!

llvm-svn: 142478
This commit is contained in:
Douglas Gregor 2011-10-19 06:04:55 +00:00
parent 5fdc4de718
commit e248eea214
8 changed files with 76 additions and 6 deletions

View File

@ -1105,6 +1105,16 @@ struct DeclaratorChunk {
/// If this is an invalid location, there is no ref-qualifier.
unsigned RefQualifierLoc;
/// \brief The location of the const-qualifier, if any.
///
/// If this is an invalid location, there is no const-qualifier.
unsigned ConstQualifierLoc;
/// \brief The location of the volatile-qualifier, if any.
///
/// If this is an invalid location, there is no volatile-qualifier.
unsigned VolatileQualifierLoc;
/// \brief The location of the 'mutable' qualifer in a lambda-declarator, if
/// any.
unsigned MutableLoc;
@ -1170,6 +1180,16 @@ struct DeclaratorChunk {
return SourceLocation::getFromRawEncoding(RefQualifierLoc);
}
/// \brief Retrieve the location of the ref-qualifier, if any.
SourceLocation getConstQualifierLoc() const {
return SourceLocation::getFromRawEncoding(ConstQualifierLoc);
}
/// \brief Retrieve the location of the ref-qualifier, if any.
SourceLocation getVolatileQualifierLoc() const {
return SourceLocation::getFromRawEncoding(VolatileQualifierLoc);
}
/// \brief Retrieve the location of the 'mutable' qualifier, if any.
SourceLocation getMutableLoc() const {
return SourceLocation::getFromRawEncoding(MutableLoc);
@ -1306,6 +1326,8 @@ struct DeclaratorChunk {
unsigned TypeQuals,
bool RefQualifierIsLvalueRef,
SourceLocation RefQualifierLoc,
SourceLocation ConstQualifierLoc,
SourceLocation VolatileQualifierLoc,
SourceLocation MutableLoc,
ExceptionSpecificationType ESpecType,
SourceLocation ESpecLoc,

View File

@ -4031,6 +4031,8 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
DeclSpec DS(AttrFactory);
bool RefQualifierIsLValueRef = true;
SourceLocation RefQualifierLoc;
SourceLocation ConstQualifierLoc;
SourceLocation VolatileQualifierLoc;
ExceptionSpecificationType ESpecType = EST_None;
SourceRange ESpecRange;
SmallVector<ParsedType, 2> DynamicExceptions;
@ -4069,8 +4071,11 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
// Parse cv-qualifier-seq[opt].
ParseTypeQualifierListOpt(DS, false /*no attributes*/);
if (!DS.getSourceRange().getEnd().isInvalid())
if (!DS.getSourceRange().getEnd().isInvalid()) {
EndLoc = DS.getSourceRange().getEnd();
ConstQualifierLoc = DS.getConstSpecLoc();
VolatileQualifierLoc = DS.getVolatileSpecLoc();
}
// Parse ref-qualifier[opt].
if (Tok.is(tok::amp) || Tok.is(tok::ampamp)) {
@ -4112,7 +4117,8 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
ParamInfo.data(), ParamInfo.size(),
DS.getTypeQualifiers(),
RefQualifierIsLValueRef,
RefQualifierLoc,
RefQualifierLoc, ConstQualifierLoc,
VolatileQualifierLoc,
/*MutableLoc=*/SourceLocation(),
ESpecType, ESpecRange.getBegin(),
DynamicExceptions.data(),

View File

@ -2280,6 +2280,8 @@ ExprResult Parser::ParseBlockLiteralExpression() {
0, 0, 0,
true, SourceLocation(),
SourceLocation(),
SourceLocation(),
SourceLocation(),
EST_None,
SourceLocation(),
0, 0, 0, 0,

View File

@ -748,6 +748,8 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
DS.getTypeQualifiers(),
/*RefQualifierIsLValueRef=*/true,
/*RefQualifierLoc=*/SourceLocation(),
/*ConstQualifierLoc=*/SourceLocation(),
/*VolatileQualifierLoc=*/SourceLocation(),
MutableLoc,
ESpecType, ESpecRange.getBegin(),
DynamicExceptions.data(),

View File

@ -151,6 +151,9 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic,
unsigned TypeQuals,
bool RefQualifierIsLvalueRef,
SourceLocation RefQualifierLoc,
SourceLocation ConstQualifierLoc,
SourceLocation
VolatileQualifierLoc,
SourceLocation MutableLoc,
ExceptionSpecificationType
ESpecType,
@ -177,6 +180,8 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic,
I.Fun.ArgInfo = 0;
I.Fun.RefQualifierIsLValueRef = RefQualifierIsLvalueRef;
I.Fun.RefQualifierLoc = RefQualifierLoc.getRawEncoding();
I.Fun.ConstQualifierLoc = ConstQualifierLoc.getRawEncoding();
I.Fun.VolatileQualifierLoc = VolatileQualifierLoc.getRawEncoding();
I.Fun.MutableLoc = MutableLoc.getRawEncoding();
I.Fun.ExceptionSpecType = ESpecType;
I.Fun.ExceptionSpecLoc = ESpecLoc.getRawEncoding();

View File

@ -7222,6 +7222,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
Declarator D(DS, Declarator::BlockContext);
D.AddTypeInfo(DeclaratorChunk::getFunction(false, false, SourceLocation(), 0,
0, 0, true, SourceLocation(),
SourceLocation(), SourceLocation(),
SourceLocation(),
EST_None, SourceLocation(),
0, 0, 0, 0, Loc, Loc, D),

View File

@ -555,6 +555,8 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state,
/*args*/ 0, 0,
/*type quals*/ 0,
/*ref-qualifier*/true, SourceLocation(),
/*const qualifier*/SourceLocation(),
/*volatile qualifier*/SourceLocation(),
/*mutable qualifier*/SourceLocation(),
/*EH*/ EST_None, SourceLocation(), 0, 0, 0, 0,
/*parens*/ loc, loc,
@ -2431,10 +2433,37 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
<< Quals;
} else {
if (FnTy->getTypeQuals() != 0) {
if (D.isFunctionDeclarator())
S.Diag(D.getIdentifierLoc(),
diag::err_invalid_qualified_function_type);
else
if (D.isFunctionDeclarator()) {
SourceRange Range = D.getIdentifierLoc();
for (unsigned I = 0, N = D.getNumTypeObjects(); I != N; ++I) {
const DeclaratorChunk &Chunk = D.getTypeObject(N-I-1);
if (Chunk.Kind == DeclaratorChunk::Function &&
Chunk.Fun.TypeQuals != 0) {
switch (Chunk.Fun.TypeQuals) {
case Qualifiers::Const:
Range = Chunk.Fun.getConstQualifierLoc();
break;
case Qualifiers::Volatile:
Range = Chunk.Fun.getVolatileQualifierLoc();
break;
case Qualifiers::Const | Qualifiers::Volatile: {
SourceLocation CLoc = Chunk.Fun.getConstQualifierLoc();
SourceLocation VLoc = Chunk.Fun.getVolatileQualifierLoc();
if (S.getSourceManager()
.isBeforeInTranslationUnit(CLoc, VLoc)) {
Range = SourceRange(CLoc, VLoc);
} else {
Range = SourceRange(VLoc, CLoc);
}
}
break;
}
break;
}
}
S.Diag(Range.getBegin(), diag::err_invalid_qualified_function_type)
<< FixItHint::CreateRemoval(Range);
} else
S.Diag(D.getIdentifierLoc(),
diag::err_invalid_qualified_typedef_function_type_use)
<< FreeFunction;

View File

@ -107,4 +107,7 @@ void test (BD &br) {
aPtr = br; // expected-error {{assigning to 'A *' from incompatible type 'B'; take the address with &}}
}
void foo1() const {} // expected-error {{type qualifier is not allowed on this function}}
void foo2() volatile {} // expected-error {{type qualifier is not allowed on this function}}
void foo3() const volatile {} // expected-error {{type qualifier is not allowed on this function}}