From 075f8f1b6bed4d1b224c74f87508534cc6392ce6 Mon Sep 17 00:00:00 2001 From: Abramo Bagnara <abramo.bagnara@gmail.com> Date: Fri, 10 Dec 2010 16:29:40 +0000 Subject: [PATCH] Added ParenType type node. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@121488 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ASTContext.h | 3 + include/clang/AST/RecursiveASTVisitor.h | 8 +++ include/clang/AST/Type.h | 45 +++++++++++++-- include/clang/AST/TypeLoc.h | 40 ++++++++++++++ include/clang/AST/TypeNodes.def | 1 + include/clang/Sema/DeclSpec.h | 67 +++++++++++++++++++++-- include/clang/Sema/Sema.h | 2 + include/clang/Serialization/ASTBitCodes.h | 4 +- lib/AST/ASTContext.cpp | 34 ++++++++++++ lib/AST/ASTDiagnostic.cpp | 6 +- lib/AST/ASTImporter.cpp | 7 +++ lib/AST/Type.cpp | 6 ++ lib/AST/TypePrinter.cpp | 6 ++ lib/CodeGen/CGDebugInfo.cpp | 4 ++ lib/CodeGen/CodeGenFunction.cpp | 5 ++ lib/Parse/ParseCXXInlineMethods.cpp | 3 +- lib/Parse/ParseDecl.cpp | 4 +- lib/Parse/ParseDeclCXX.cpp | 2 +- lib/Parse/Parser.cpp | 14 ++--- lib/Sema/SemaCodeComplete.cpp | 3 + lib/Sema/SemaDecl.cpp | 20 ++++--- lib/Sema/SemaDeclCXX.cpp | 6 +- lib/Sema/SemaExceptionSpec.cpp | 2 + lib/Sema/SemaTemplate.cpp | 4 +- lib/Sema/SemaType.cpp | 15 ++++- lib/Sema/TreeTransform.h | 30 ++++++++++ lib/Serialization/ASTReader.cpp | 13 +++++ lib/Serialization/ASTWriter.cpp | 9 +++ tools/libclang/CIndex.cpp | 5 ++ 29 files changed, 329 insertions(+), 39 deletions(-) diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 9b5826b5d9..745b6a38db 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -101,6 +101,7 @@ class ASTContext { llvm::FoldingSet<SubstTemplateTypeParmType> SubstTemplateTypeParmTypes; llvm::ContextualFoldingSet<TemplateSpecializationType, ASTContext&> TemplateSpecializationTypes; + llvm::FoldingSet<ParenType> ParenTypes; llvm::FoldingSet<ElaboratedType> ElaboratedTypes; llvm::FoldingSet<DependentNameType> DependentNameTypes; llvm::ContextualFoldingSet<DependentTemplateSpecializationType, ASTContext&> @@ -685,6 +686,8 @@ public: const TemplateArgumentListInfo &Args, QualType Canon = QualType()); + QualType getParenType(QualType NamedType); + QualType getElaboratedType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, QualType NamedType); diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 269f03d545..085e65ce02 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -718,6 +718,10 @@ DEF_TRAVERSE_TYPE(TemplateSpecializationType, { DEF_TRAVERSE_TYPE(InjectedClassNameType, { }) +DEF_TRAVERSE_TYPE(ParenType, { + TRY_TO(TraverseType(T->getInnerType())); + }) + DEF_TRAVERSE_TYPE(ElaboratedType, { if (T->getQualifier()) { TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); @@ -915,6 +919,10 @@ DEF_TRAVERSE_TYPELOC(TemplateSpecializationType, { DEF_TRAVERSE_TYPELOC(InjectedClassNameType, { }) +DEF_TRAVERSE_TYPELOC(ParenType, { + TRY_TO(TraverseTypeLoc(TL.getInnerLoc())); + }) + // FIXME: use the sourceloc on qualifier? DEF_TRAVERSE_TYPELOC(ElaboratedType, { if (TL.getTypePtr()->getQualifier()) { diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index be23abd095..19f7f47837 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -661,6 +661,12 @@ public: return getSplitDesugaredType(*this); } + /// IgnoreParens - Returns the specified type after dropping any + /// outer-level parentheses. + QualType IgnoreParens() const { + return QualType::IgnoreParens(*this); + } + /// operator==/!= - Indicate whether the specified types and qualifiers are /// identical. friend bool operator==(const QualType &LHS, const QualType &RHS) { @@ -724,6 +730,7 @@ private: static bool isConstant(QualType T, ASTContext& Ctx); static QualType getDesugaredType(QualType T, ASTContext &Context); static SplitQualType getSplitDesugaredType(QualType T); + static QualType IgnoreParens(QualType T); }; } // end clang. @@ -1392,6 +1399,36 @@ public: static bool classof(const ComplexType *) { return true; } }; +/// ParenType - Sugar for parentheses used when specifying types. +/// +class ParenType : public Type, public llvm::FoldingSetNode { + QualType Inner; + + ParenType(QualType InnerType, QualType CanonType) : + Type(Paren, CanonType, InnerType->isDependentType(), + InnerType->isVariablyModifiedType()), + Inner(InnerType) { + } + friend class ASTContext; // ASTContext creates these. + +public: + + QualType getInnerType() const { return Inner; } + + bool isSugared() const { return true; } + QualType desugar() const { return getInnerType(); } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getInnerType()); + } + static void Profile(llvm::FoldingSetNodeID &ID, QualType Inner) { + Inner.Profile(ID); + } + + static bool classof(const Type *T) { return T->getTypeClass() == Paren; } + static bool classof(const ParenType *) { return true; } +}; + /// PointerType - C99 6.7.5.1 - Pointer Declarators. /// class PointerType : public Type, public llvm::FoldingSetNode { @@ -2026,12 +2063,12 @@ class FunctionType : public Type { QualType ResultType; public: - // This class is used for passing arround the information needed to + // This class is used for passing around the information needed to // construct a call. It is not actually used for storage, just for // factoring together common arguments. - // If you add a field (say Foo), other than the obvious places (both, constructors, - // compile failures), what you need to update is - // * Operetor== + // If you add a field (say Foo), other than the obvious places (both, + // constructors, compile failures), what you need to update is + // * Operator== // * getFoo // * withFoo // * functionType. Add Foo, getFoo. diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index e955d07770..1ec0e6cdd1 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -694,6 +694,46 @@ public: } }; +struct ParenLocInfo { + SourceLocation LParenLoc; + SourceLocation RParenLoc; +}; + +class ParenTypeLoc + : public ConcreteTypeLoc<UnqualTypeLoc, ParenTypeLoc, ParenType, + ParenLocInfo> { +public: + SourceLocation getLParenLoc() const { + return this->getLocalData()->LParenLoc; + } + SourceLocation getRParenLoc() const { + return this->getLocalData()->RParenLoc; + } + void setLParenLoc(SourceLocation Loc) { + this->getLocalData()->LParenLoc = Loc; + } + void setRParenLoc(SourceLocation Loc) { + this->getLocalData()->RParenLoc = Loc; + } + + SourceRange getLocalSourceRange() const { + return SourceRange(getLParenLoc(), getRParenLoc()); + } + + void initializeLocal(SourceLocation Loc) { + setLParenLoc(Loc); + setRParenLoc(Loc); + } + + TypeLoc getInnerLoc() const { + return getInnerTypeLoc(); + } + + QualType getInnerType() const { + return this->getTypePtr()->getInnerType(); + } +}; + struct PointerLikeLocInfo { SourceLocation StarLoc; diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def index 9cb56861a9..5355af1c08 100644 --- a/include/clang/AST/TypeNodes.def +++ b/include/clang/AST/TypeNodes.def @@ -79,6 +79,7 @@ ABSTRACT_TYPE(Function, Type) TYPE(FunctionProto, FunctionType) TYPE(FunctionNoProto, FunctionType) DEPENDENT_TYPE(UnresolvedUsing, Type) +NON_CANONICAL_TYPE(Paren, Type) NON_CANONICAL_TYPE(Typedef, Type) NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOfExpr, Type) NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOf, Type) diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index 5c043cd261..bd419e3e69 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -26,6 +26,7 @@ #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/Specifiers.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Support/ErrorHandling.h" namespace clang { class LangOptions; @@ -799,7 +800,7 @@ typedef llvm::SmallVector<Token, 4> CachedTokens; /// This is intended to be a small value object. struct DeclaratorChunk { enum { - Pointer, Reference, Array, Function, BlockPointer, MemberPointer + Pointer, Reference, Array, Function, BlockPointer, MemberPointer, Paren } Kind; /// Loc - The place where this type was defined. @@ -1006,6 +1007,7 @@ struct DeclaratorChunk { case DeclaratorChunk::Reference: return Ref.destroy(); case DeclaratorChunk::Array: return Arr.destroy(); case DeclaratorChunk::MemberPointer: return Mem.destroy(); + case DeclaratorChunk::Paren: return; } } @@ -1013,14 +1015,16 @@ struct DeclaratorChunk { /// them. const AttributeList *getAttrs() const { switch (Kind) { - default: assert(0 && "Unknown declarator kind!"); case Pointer: return Ptr.AttrList; case Reference: return Ref.AttrList; case MemberPointer: return Mem.AttrList; case Array: return 0; case Function: return 0; case BlockPointer: return Cls.AttrList; + case Paren: return 0; } + llvm_unreachable("Unknown declarator kind!"); + return 0; } @@ -1104,6 +1108,18 @@ struct DeclaratorChunk { new (I.Mem.ScopeMem.Mem) CXXScopeSpec(SS); return I; } + + /// getParen - Return a DeclaratorChunk for a paren. + /// + static DeclaratorChunk getParen(SourceLocation LParenLoc, + SourceLocation RParenLoc) { + DeclaratorChunk I; + I.Kind = Paren; + I.Loc = LParenLoc; + I.EndLoc = RParenLoc; + return I; + } + }; /// Declarator - Information about one declarator, including the parsed type @@ -1323,11 +1339,52 @@ public: DeclTypeInfo.erase(DeclTypeInfo.begin()); } + /// isFunctionDeclarator - This method returns true if the declarator + /// is a function declarator (looking through parentheses). + /// If true is returned, then the reference type parameter idx is + /// assigned with the index of the declaration chunk. + bool isFunctionDeclarator(unsigned& idx) const { + for (unsigned i = 0, i_end = DeclTypeInfo.size(); i < i_end; ++i) { + switch (DeclTypeInfo[i].Kind) { + case DeclaratorChunk::Function: + idx = i; + return true; + case DeclaratorChunk::Paren: + continue; + case DeclaratorChunk::Pointer: + case DeclaratorChunk::Reference: + case DeclaratorChunk::Array: + case DeclaratorChunk::BlockPointer: + case DeclaratorChunk::MemberPointer: + return false; + } + llvm_unreachable("Invalid type chunk"); + return false; + } + return false; + } + /// isFunctionDeclarator - Once this declarator is fully parsed and formed, - /// this method returns true if the identifier is a function declarator. + /// this method returns true if the identifier is a function declarator + /// (looking through parentheses). bool isFunctionDeclarator() const { - return !DeclTypeInfo.empty() && - DeclTypeInfo[0].Kind == DeclaratorChunk::Function; + unsigned index; + return isFunctionDeclarator(index); + } + + /// getFunctionTypeInfo - Retrieves the function type info object + /// (looking through parentheses). + DeclaratorChunk::FunctionTypeInfo &getFunctionTypeInfo() { + assert(isFunctionDeclarator() && "Not a function declarator!"); + unsigned index; + isFunctionDeclarator(index); + return DeclTypeInfo[index].Fun; + } + + /// getFunctionTypeInfo - Retrieves the function type info object + /// (looking through parentheses). + const DeclaratorChunk::FunctionTypeInfo &getFunctionTypeInfo() const { + return const_cast<Declarator*>(this)->getFunctionTypeInfo(); } /// AddAttributes - simply adds the attribute list to the Declarator. diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 541f726e5a..0aff2f6bff 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -619,6 +619,8 @@ public: DeclarationName Entity); QualType BuildBlockPointerType(QualType T, SourceLocation Loc, DeclarationName Entity); + QualType BuildParenType(QualType T); + TypeSourceInfo *GetTypeForDeclarator(Declarator &D, Scope *S, TagDecl **OwnedDecl = 0); TypeSourceInfo *GetTypeSourceInfoForDeclarator(Declarator &D, QualType T, diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h index 29eb49106f..d32cc2717b 100644 --- a/include/clang/Serialization/ASTBitCodes.h +++ b/include/clang/Serialization/ASTBitCodes.h @@ -549,7 +549,9 @@ namespace clang { /// \brief A DependentTemplateSpecializationType record. TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION = 32, /// \brief A DependentSizedArrayType record. - TYPE_DEPENDENT_SIZED_ARRAY = 33 + TYPE_DEPENDENT_SIZED_ARRAY = 33, + /// \brief A ParenType record. + TYPE_PAREN = 34 }; /// \brief The type IDs for special types constructed by semantic diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index dfdc505b1a..ecba4a136f 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -811,6 +811,9 @@ ASTContext::getTypeInfo(const Type *T) { return getTypeInfo(cast<SubstTemplateTypeParmType>(T)-> getReplacementType().getTypePtr()); + case Type::Paren: + return getTypeInfo(cast<ParenType>(T)->getInnerType().getTypePtr()); + case Type::Typedef: { const TypedefDecl *Typedef = cast<TypedefType>(T)->getDecl(); std::pair<uint64_t, unsigned> Info @@ -1147,6 +1150,13 @@ static QualType getExtFunctionType(ASTContext& Context, QualType T, return T; ResultType = Context.getPointerType(ResultType); + } else if (const ParenType *Paren = T->getAs<ParenType>()) { + QualType Inner = Paren->getInnerType(); + ResultType = getExtFunctionType(Context, Inner, Info); + if (ResultType == Inner) + return T; + + ResultType = Context.getParenType(ResultType); } else if (const BlockPointerType *BlockPointer = T->getAs<BlockPointerType>()) { QualType Pointee = BlockPointer->getPointeeType(); @@ -2095,6 +2105,30 @@ ASTContext::getElaboratedType(ElaboratedTypeKeyword Keyword, return QualType(T, 0); } +QualType +ASTContext::getParenType(QualType InnerType) { + llvm::FoldingSetNodeID ID; + ParenType::Profile(ID, InnerType); + + void *InsertPos = 0; + ParenType *T = ParenTypes.FindNodeOrInsertPos(ID, InsertPos); + if (T) + return QualType(T, 0); + + QualType Canon = InnerType; + if (!Canon.isCanonical()) { + Canon = getCanonicalType(InnerType); + ParenType *CheckT = ParenTypes.FindNodeOrInsertPos(ID, InsertPos); + assert(!CheckT && "Paren canonical type broken"); + (void)CheckT; + } + + T = new (*this) ParenType(InnerType, Canon); + Types.push_back(T); + ParenTypes.InsertNode(T, InsertPos); + return QualType(T, 0); +} + QualType ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, const IdentifierInfo *Name, diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp index 8d5e408465..bd128f0514 100644 --- a/lib/AST/ASTDiagnostic.cpp +++ b/lib/AST/ASTDiagnostic.cpp @@ -32,7 +32,11 @@ static QualType Desugar(ASTContext &Context, QualType QT, bool &ShouldAKA) { QT = cast<ElaboratedType>(Ty)->desugar(); continue; } - + // ... or a paren type ... + if (isa<ParenType>(Ty)) { + QT = cast<ParenType>(Ty)->desugar(); + continue; + } // ...or a substituted template type parameter. if (isa<SubstTemplateTypeParmType>(Ty)) { QT = cast<SubstTemplateTypeParmType>(Ty)->desugar(); diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 4094c88e13..8415977349 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -553,6 +553,13 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, break; + case Type::Paren: + if (!IsStructurallyEquivalent(Context, + cast<ParenType>(T1)->getInnerType(), + cast<ParenType>(T2)->getInnerType())) + return false; + break; + case Type::Typedef: if (!IsStructurallyEquivalent(Context, cast<TypedefType>(T1)->getDecl(), diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 705b097212..ed05a39305 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -171,6 +171,12 @@ SplitQualType QualType::getSplitDesugaredType(QualType T) { } } +QualType QualType::IgnoreParens(QualType T) { + while (const ParenType *PT = T->getAs<ParenType>()) + T = PT->getInnerType(); + return T; +} + /// getUnqualifiedDesugaredType - Pull any qualifiers and syntactic /// sugar off the given type. This should produce an object of the /// same dynamic type as the canonical type. diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index 0e37acb40f..15c3fb2fbf 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -618,6 +618,12 @@ void TypePrinter::printElaborated(const ElaboratedType *T, std::string &S) { S = MyString + ' ' + S; } +void TypePrinter::printParen(const ParenType *T, std::string &S) { + if (!S.empty() && !isa<FunctionType>(T->getInnerType())) + S = '(' + S + ')'; + print(T->getInnerType(), S); +} + void TypePrinter::printDependentName(const DependentNameType *T, std::string &S) { std::string MyString; diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 3e77769466..615972afbc 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -1327,6 +1327,9 @@ static QualType UnwrapTypeForDebugInfo(QualType T) { case Type::Elaborated: T = cast<ElaboratedType>(T)->getNamedType(); break; + case Type::Paren: + T = cast<ParenType>(T)->getInnerType(); + break; case Type::SubstTemplateTypeParm: T = cast<SubstTemplateTypeParmType>(T)->getReplacementType(); break; @@ -1422,6 +1425,7 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, case Type::TemplateSpecialization: case Type::Elaborated: + case Type::Paren: case Type::SubstTemplateTypeParm: case Type::TypeOfExpr: case Type::TypeOf: diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index efeca2d538..7bd0c3da9e 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -656,6 +656,11 @@ llvm::Value *CodeGenFunction::EmitVLASize(QualType Ty) { return 0; } + if (const ParenType *PT = dyn_cast<ParenType>(Ty)) { + EmitVLASize(PT->getInnerType()); + return 0; + } + const PointerType *PT = Ty->getAs<PointerType>(); assert(PT && "unknown VM type!"); EmitVLASize(PT->getPointeeType()); diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp index 718c71be02..2341ad39f0 100644 --- a/lib/Parse/ParseCXXInlineMethods.cpp +++ b/lib/Parse/ParseCXXInlineMethods.cpp @@ -22,8 +22,7 @@ using namespace clang; /// and store its tokens for parsing after the C++ class is complete. Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D, const ParsedTemplateInfo &TemplateInfo) { - assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function && - "This isn't a function declarator!"); + assert(D.isFunctionDeclarator() && "This isn't a function declarator!"); assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) && "Current token not a '{', ':' or 'try'!"); diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 9a682b064d..53cccc0819 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -3037,10 +3037,10 @@ void Parser::ParseParenDeclarator(Declarator &D) { ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator); // Match the ')'. - SourceLocation Loc = MatchRHSPunctuation(tok::r_paren, StartLoc); + SourceLocation EndLoc = MatchRHSPunctuation(tok::r_paren, StartLoc); + D.AddTypeInfo(DeclaratorChunk::getParen(StartLoc, EndLoc), EndLoc); D.setGroupingParens(hadGroupingParens); - D.SetRangeEnd(Loc); return; } diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 68797a7542..a2c87f85c3 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -1239,7 +1239,7 @@ void Parser::HandleMemberFunctionDefaultArgs(Declarator& DeclaratorInfo, // has any default arguments, we'll need to parse them later. LateParsedMethodDeclaration *LateMethod = 0; DeclaratorChunk::FunctionTypeInfo &FTI - = DeclaratorInfo.getTypeObject(0).Fun; + = DeclaratorInfo.getFunctionTypeInfo(); for (unsigned ParamIdx = 0; ParamIdx < FTI.NumArgs; ++ParamIdx) { if (LateMethod || FTI.ArgInfo[ParamIdx].DefaultArgTokens) { if (!LateMethod) { diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index f5e4bfb649..f79a2f68c7 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -601,14 +601,13 @@ bool Parser::isDeclarationAfterDeclarator() const { /// \brief Determine whether the current token, if it occurs after a /// declarator, indicates the start of a function definition. bool Parser::isStartOfFunctionDefinition(const ParsingDeclarator &Declarator) { - assert(Declarator.getTypeObject(0).Kind == DeclaratorChunk::Function && - "Isn't a function declarator"); + assert(Declarator.isFunctionDeclarator() && "Isn't a function declarator"); if (Tok.is(tok::l_brace)) // int X() {} return true; // Handle K&R C argument lists: int X(f) int f; {} if (!getLang().CPlusPlus && - Declarator.getTypeObject(0).Fun.isKNRPrototype()) + Declarator.getFunctionTypeInfo().isKNRPrototype()) return isDeclarationSpecifier(); return Tok.is(tok::colon) || // X() : Base() {} (used for ctors) @@ -712,11 +711,8 @@ Parser::ParseDeclarationOrFunctionDefinition(AttributeList *Attr, /// decl-specifier-seq[opt] declarator function-try-block /// Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, - const ParsedTemplateInfo &TemplateInfo) { - const DeclaratorChunk &FnTypeInfo = D.getTypeObject(0); - assert(FnTypeInfo.Kind == DeclaratorChunk::Function && - "This isn't a function declarator!"); - const DeclaratorChunk::FunctionTypeInfo &FTI = FnTypeInfo.Fun; + const ParsedTemplateInfo &TemplateInfo) { + const DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); // If this is C90 and the declspecs were completely missing, fudge in an // implicit int. We do this here because this is the only place where @@ -793,7 +789,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, /// types for a function with a K&R-style identifier list for arguments. void Parser::ParseKNRParamDeclarations(Declarator &D) { // We know that the top-level of this declarator is a function. - DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun; + DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); // Enter function-declaration scope, limiting any declarators to the // function prototype scope, including parameter declarators. diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 0e30a2b0ba..2394629be5 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -1919,6 +1919,9 @@ static std::string FormatFunctionParameter(ASTContext &Context, if (BlockPointerTypeLoc *BlockPtr = dyn_cast<BlockPointerTypeLoc>(&TL)) { TL = BlockPtr->getPointeeLoc(); + // Skip any paren typeloc. + while (ParenTypeLoc *ParenPtr = dyn_cast<ParenTypeLoc>(&TL)) + TL = ParenPtr->getInnerLoc(); Block = dyn_cast<FunctionProtoTypeLoc>(&TL); } break; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 1112d85b8b..522ba36760 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2571,6 +2571,15 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T, FixedType = Context.getPointerType(FixedType); return Qs.apply(Context, FixedType); } + if (const ParenType* PTy = dyn_cast<ParenType>(Ty)) { + QualType Inner = PTy->getInnerType(); + QualType FixedType = + TryToFixInvalidVariablyModifiedType(Inner, Context, SizeIsNegative, + Oversized); + if (FixedType.isNull()) return FixedType; + FixedType = Context.getParenType(FixedType); + return Qs.apply(Context, FixedType); + } const VariableArrayType* VLATy = dyn_cast<VariableArrayType>(T); if (!VLATy) @@ -3456,7 +3465,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // - the type R of the function is some kind of typedef or other reference // to a type name (which eventually refers to a function type). bool HasPrototype = - (D.getNumTypeObjects() && D.getTypeObject(0).Fun.hasPrototype) || + (D.isFunctionDeclarator() && D.getFunctionTypeInfo().hasPrototype) || (!isa<FunctionType>(R.getTypePtr()) && R->isFunctionProtoType()); NewFD = FunctionDecl::Create(Context, DC, @@ -3754,7 +3763,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // declaration NewFD, if they are available. First scavenge them into Params. llvm::SmallVector<ParmVarDecl*, 16> Params; if (D.getNumTypeObjects() > 0) { - DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun; + DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); // Check for C99 6.7.5.3p10 - foo(void) is a non-varargs // function that takes no arguments, not a function that takes a @@ -5088,9 +5097,7 @@ ParmVarDecl *Sema::CheckParameter(DeclContext *DC, void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, SourceLocation LocAfterDecls) { - assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function && - "Not a function declarator!"); - DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun; + DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); // Verify 6.9.1p6: 'every identifier in the identifier list shall be declared' // for a K&R function. @@ -5124,8 +5131,7 @@ void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) { assert(getCurFunctionDecl() == 0 && "Function parsing confused"); - assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function && - "Not a function declarator!"); + assert(D.isFunctionDeclarator() && "Not a function declarator!"); Scope *ParentScope = FnBodyScope->getParent(); Decl *DP = HandleDeclarator(ParentScope, D, diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index b5e6321276..be1979e26e 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -2835,7 +2835,7 @@ QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R, SC = SC_None; } - DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun; + DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); if (FTI.TypeQuals != 0) { if (FTI.TypeQuals & Qualifiers::Const) Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor) @@ -2984,7 +2984,7 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R, << SourceRange(D.getIdentifierLoc()); } - DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun; + DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); if (FTI.TypeQuals != 0 && !D.isInvalidType()) { if (FTI.TypeQuals & Qualifiers::Const) Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor) @@ -3074,7 +3074,7 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R, Diag(D.getIdentifierLoc(), diag::err_conv_function_with_params); // Delete the parameters. - D.getTypeObject(0).Fun.freeArgs(); + D.getFunctionTypeInfo().freeArgs(); D.setInvalidType(); } else if (Proto->isVariadic()) { Diag(D.getIdentifierLoc(), diag::err_conv_function_variadic); diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp index c902e77870..885e52dd76 100644 --- a/lib/Sema/SemaExceptionSpec.cpp +++ b/lib/Sema/SemaExceptionSpec.cpp @@ -81,6 +81,7 @@ bool Sema::CheckSpecifiedExceptionType(QualType T, const SourceRange &Range) { /// to member to a function with an exception specification. This means that /// it is invalid to add another level of indirection. bool Sema::CheckDistantExceptionSpec(QualType T) { + T = T.IgnoreParens(); if (const PointerType *PT = T->getAs<PointerType>()) T = PT->getPointeeType(); else if (const MemberPointerType *PT = T->getAs<MemberPointerType>()) @@ -88,6 +89,7 @@ bool Sema::CheckDistantExceptionSpec(QualType T) { else return false; + T = T.IgnoreParens(); const FunctionProtoType *FnT = T->getAs<FunctionProtoType>(); if (!FnT) return false; diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index ad0d42a11a..7539a56965 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -4336,9 +4336,7 @@ Decl *Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope, MultiTemplateParamsArg TemplateParameterLists, Declarator &D) { assert(getCurFunctionDecl() == 0 && "Function parsing confused"); - assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function && - "Not a function declarator!"); - DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun; + DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); if (FTI.hasPrototype) { // FIXME: Diagnose arguments without names in C. diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 5f86010602..23c159fbc5 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -521,6 +521,11 @@ QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc, return Context.getQualifiedType(T, Qs); } +/// \brief Build a paren type including \p T. +QualType Sema::BuildParenType(QualType T) { + return Context.getParenType(T); +} + /// \brief Build a pointer type. /// /// \param T The type to which we'll be building a pointer. @@ -1002,7 +1007,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, // Check for auto functions and trailing return type and adjust the // return type accordingly. if (getLangOptions().CPlusPlus0x && D.isFunctionDeclarator()) { - const DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun; + const DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); if (T == Context.UndeducedAutoTy) { if (FTI.TrailingReturnType) { T = GetTypeFromParser(ParsedType::getFromOpaquePtr(FTI.TrailingReturnType), @@ -1082,6 +1087,9 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, DeclaratorChunk &DeclType = D.getTypeObject(e-i-1); switch (DeclType.Kind) { default: assert(0 && "Unknown decltype!"); + case DeclaratorChunk::Paren: + T = BuildParenType(T); + break; case DeclaratorChunk::BlockPointer: // If blocks are disabled, emit an error. if (!LangOpts.Blocks) @@ -1678,6 +1686,11 @@ namespace { } // FIXME: exception specs } + void VisitParenTypeLoc(ParenTypeLoc TL) { + assert(Chunk.Kind == DeclaratorChunk::Paren); + TL.setLParenLoc(Chunk.Loc); + TL.setRParenLoc(Chunk.EndLoc); + } void VisitTypeLoc(TypeLoc TL) { llvm_unreachable("unsupported TypeLoc kind in declarator!"); diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index c0bafc7cb0..9f6f84bec8 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -519,6 +519,14 @@ public: SourceLocation TemplateLoc, const TemplateArgumentListInfo &Args); + /// \brief Build a new parenthesized type. + /// + /// By default, builds a new ParenType type from the inner type. + /// Subclasses may override this routine to provide different behavior. + QualType RebuildParenType(QualType InnerType) { + return SemaRef.Context.getParenType(InnerType); + } + /// \brief Build a new qualified name type. /// /// By default, builds a new ElaboratedType type from the keyword, @@ -3371,6 +3379,28 @@ TreeTransform<Derived>::TransformElaboratedType(TypeLocBuilder &TLB, return Result; } +template<typename Derived> +QualType +TreeTransform<Derived>::TransformParenType(TypeLocBuilder &TLB, + ParenTypeLoc TL) { + QualType Inner = getDerived().TransformType(TLB, TL.getInnerLoc()); + if (Inner.isNull()) + return QualType(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + Inner != TL.getInnerLoc().getType()) { + Result = getDerived().RebuildParenType(Inner); + if (Result.isNull()) + return QualType(); + } + + ParenTypeLoc NewTL = TLB.push<ParenTypeLoc>(Result); + NewTL.setLParenLoc(TL.getLParenLoc()); + NewTL.setRParenLoc(TL.getRParenLoc()); + return Result; +} + template<typename Derived> QualType TreeTransform<Derived>::TransformDependentNameType(TypeLocBuilder &TLB, DependentNameTypeLoc TL) { diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index c3c0aeae67..4e0a7b783b 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -2916,6 +2916,15 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) { return T; } + case TYPE_PAREN: { + if (Record.size() != 1) { + Error("incorrect encoding of paren type"); + return QualType(); + } + QualType InnerType = GetType(Record[0]); + return Context->getParenType(InnerType); + } + case TYPE_ELABORATED: { unsigned Idx = 0; ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++]; @@ -3186,6 +3195,10 @@ void TypeLocReader::VisitTemplateSpecializationTypeLoc( TL.getTypePtr()->getArg(i).getKind(), Record, Idx)); } +void TypeLocReader::VisitParenTypeLoc(ParenTypeLoc TL) { + TL.setLParenLoc(ReadSourceLocation(Record, Idx)); + TL.setRParenLoc(ReadSourceLocation(Record, Idx)); +} void TypeLocReader::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) { TL.setKeywordLoc(ReadSourceLocation(Record, Idx)); TL.setQualifierRange(Reader.ReadSourceRange(F, Record, Idx)); diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index e95e422fbd..7b405e9c8b 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -298,6 +298,11 @@ ASTTypeWriter::VisitDependentTemplateSpecializationType( Code = TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION; } +void ASTTypeWriter::VisitParenType(const ParenType *T) { + Writer.AddTypeRef(T->getInnerType(), Record); + Code = TYPE_PAREN; +} + void ASTTypeWriter::VisitElaboratedType(const ElaboratedType *T) { Record.push_back(T->getKeyword()); Writer.AddNestedNameSpecifier(T->getQualifier(), Record); @@ -467,6 +472,10 @@ void TypeLocWriter::VisitTemplateSpecializationTypeLoc( Writer.AddTemplateArgumentLocInfo(TL.getArgLoc(i).getArgument().getKind(), TL.getArgLoc(i).getLocInfo(), Record); } +void TypeLocWriter::VisitParenTypeLoc(ParenTypeLoc TL) { + Writer.AddSourceLocation(TL.getLParenLoc(), Record); + Writer.AddSourceLocation(TL.getRParenLoc(), Record); +} void TypeLocWriter::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) { Writer.AddSourceLocation(TL.getKeywordLoc(), Record); Writer.AddSourceRange(TL.getQualifierRange(), Record); diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index d9aec47558..e8c1a745bf 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -326,6 +326,7 @@ public: bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL); bool VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL); bool VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL); + bool VisitParenTypeLoc(ParenTypeLoc TL); bool VisitPointerTypeLoc(PointerTypeLoc TL); bool VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL); bool VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL); @@ -1361,6 +1362,10 @@ bool CursorVisitor::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) { return Visit(TL.getPointeeLoc()); } +bool CursorVisitor::VisitParenTypeLoc(ParenTypeLoc TL) { + return Visit(TL.getInnerLoc()); +} + bool CursorVisitor::VisitPointerTypeLoc(PointerTypeLoc TL) { return Visit(TL.getPointeeLoc()); } -- 2.40.0