diff options
author | dim <dim@FreeBSD.org> | 2011-02-26 22:09:03 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2011-02-26 22:09:03 +0000 |
commit | a0fb00f9837bd0d2e5948f16f6a6b82a7a628f51 (patch) | |
tree | abae0246ec9156cc1a7cbb947b2b0dfe95fa3189 /lib/Sema/SemaType.cpp | |
parent | 39fcc9a984e2820e4ea0fa2ac4abd17d9f3a31df (diff) | |
download | FreeBSD-src-a0fb00f9837bd0d2e5948f16f6a6b82a7a628f51.zip FreeBSD-src-a0fb00f9837bd0d2e5948f16f6a6b82a7a628f51.tar.gz |
Vendor import of clang trunk r126547:
http://llvm.org/svn/llvm-project/cfe/trunk@126547
Diffstat (limited to 'lib/Sema/SemaType.cpp')
-rw-r--r-- | lib/Sema/SemaType.cpp | 187 |
1 files changed, 129 insertions, 58 deletions
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index c88baa5..ba80076 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. /// @@ -1450,8 +1500,12 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, if (D.getAttributes()) distributeTypeAttrsFromDeclarator(state, T); + // C++0x [dcl.spec.auto]p5: reject 'auto' if it is not in an allowed context. + // In C++0x, a function declarator using 'auto' must have a trailing return + // type (this is checked later) and we can skip this. In other languages + // using auto, we need to check regardless. if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto && - !D.isFunctionDeclarator()) { + (!getLangOptions().CPlusPlus0x || !D.isFunctionDeclarator())) { int Error = -1; switch (D.getContext()) { @@ -1483,7 +1537,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, break; case Declarator::TypeNameContext: if (!AutoAllowedInTypeName) - Error = 8; // Generic + Error = 10; // Generic break; case Declarator::FileContext: case Declarator::BlockContext: @@ -1492,6 +1546,32 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, break; } + if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) + Error = 8; + + // In Objective-C it is an error to use 'auto' on a function declarator. + if (D.isFunctionDeclarator()) + Error = 9; + + // C++0x [dcl.spec.auto]p2: 'auto' is always fine if the declarator + // contains a trailing return type. That is only legal at the outermost + // level. Check all declarator chunks (outermost first) anyway, to give + // better diagnostics. + if (getLangOptions().CPlusPlus0x && Error != -1) { + for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) { + unsigned chunkIndex = e - i - 1; + state.setCurrentChunkIndex(chunkIndex); + DeclaratorChunk &DeclType = D.getTypeObject(chunkIndex); + if (DeclType.Kind == DeclaratorChunk::Function) { + const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun; + if (FTI.TrailingReturnType) { + Error = -1; + break; + } + } + } + } + if (Error != -1) { Diag(D.getDeclSpec().getTypeSpecTypeLoc(), diag::err_auto_not_allowed) << Error; @@ -1499,7 +1579,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, D.setInvalidType(true); } } - + if (T.isNull()) return Context.getNullTypeSourceInfo(); @@ -1600,21 +1680,6 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, // of the type, otherwise the argument list is (). const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun; - // C99 6.7.5.3p1: The return type may not be a function or array type. - // For conversion functions, we'll diagnose this particular error later. - if ((T->isArrayType() || T->isFunctionType()) && - (D.getName().getKind() != UnqualifiedId::IK_ConversionFunctionId)) { - unsigned diagID = diag::err_func_returning_array_function; - // Last processing chunk in block context means this function chunk - // represents the block. - if (chunkIndex == 0 && - D.getContext() == Declarator::BlockLiteralContext) - diagID = diag::err_block_returning_array_function; - Diag(DeclType.Loc, diagID) << T->isFunctionType() << T; - T = Context.IntTy; - D.setInvalidType(true); - } - // Check for auto functions and trailing return type and adjust the // return type accordingly. if (!D.isInvalidType()) { @@ -1627,8 +1692,13 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, T = Context.IntTy; D.setInvalidType(true); } else if (FTI.TrailingReturnType) { - if (T.hasQualifiers() || !isa<AutoType>(T)) { - // T must be exactly 'auto' at this point. See CWG issue 681. + // T must be exactly 'auto' at this point. See CWG issue 681. + if (isa<ParenType>(T)) { + Diag(D.getDeclSpec().getTypeSpecTypeLoc(), + diag::err_trailing_return_in_parens) + << T << D.getDeclSpec().getSourceRange(); + D.setInvalidType(true); + } else if (T.hasQualifiers() || !isa<AutoType>(T)) { Diag(D.getDeclSpec().getTypeSpecTypeLoc(), diag::err_trailing_return_without_auto) << T << D.getDeclSpec().getSourceRange(); @@ -1641,48 +1711,48 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, } } + // C99 6.7.5.3p1: The return type may not be a function or array type. + // For conversion functions, we'll diagnose this particular error later. + if ((T->isArrayType() || T->isFunctionType()) && + (D.getName().getKind() != UnqualifiedId::IK_ConversionFunctionId)) { + unsigned diagID = diag::err_func_returning_array_function; + // Last processing chunk in block context means this function chunk + // represents the block. + if (chunkIndex == 0 && + D.getContext() == Declarator::BlockLiteralContext) + diagID = diag::err_block_returning_array_function; + Diag(DeclType.Loc, diagID) << T->isFunctionType() << T; + T = Context.IntTy; + D.setInvalidType(true); + } + // 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. @@ -1825,6 +1895,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, break; case NestedNameSpecifier::Namespace: + case NestedNameSpecifier::NamespaceAlias: case NestedNameSpecifier::Global: llvm_unreachable("Nested-name-specifier must name a type"); break; @@ -2047,7 +2118,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, break; } } - + if (T.isNull()) return Context.getNullTypeSourceInfo(); else if (D.isInvalidType()) |