From: John McCall Date: Wed, 13 Jan 2010 20:03:27 +0000 (+0000) Subject: Add type source information for both kinds of typeof types. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cfb708c354e2f30ccc5cba9d644650f408a1ec3e;p=clang Add type source information for both kinds of typeof types. Patch by Enea Zaffanella. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93344 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index 3e74d07ff7..c36c0ffde3 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -1029,18 +1029,88 @@ class ComplexTypeLoc : public InheritingConcreteTypeLoc { }; -// FIXME: location of the 'typeof' and parens (the expression is -// carried by the type). -class TypeOfExprTypeLoc : public InheritingConcreteTypeLoc { +struct TypeofLocInfo { + SourceLocation TypeofLoc; + SourceLocation LParenLoc; + SourceLocation RParenLoc; }; -// FIXME: location of the 'typeof' and parens; also the TypeSourceInfo -// for the inner type, or (maybe) just express that inline to the TypeLoc. -class TypeOfTypeLoc : public InheritingConcreteTypeLoc { +struct TypeOfExprTypeLocInfo : public TypeofLocInfo { +}; + +struct TypeOfTypeLocInfo : public TypeofLocInfo { + TypeSourceInfo* UnderlyingTInfo; +}; + +template +class TypeofLikeTypeLoc + : public ConcreteTypeLoc { +public: + SourceLocation getTypeofLoc() const { + return this->getLocalData()->TypeofLoc; + } + void setTypeofLoc(SourceLocation Loc) { + this->getLocalData()->TypeofLoc = Loc; + } + + SourceLocation getLParenLoc() const { + return this->getLocalData()->LParenLoc; + } + void setLParenLoc(SourceLocation Loc) { + this->getLocalData()->LParenLoc = Loc; + } + + SourceLocation getRParenLoc() const { + return this->getLocalData()->RParenLoc; + } + void setRParenLoc(SourceLocation Loc) { + this->getLocalData()->RParenLoc = Loc; + } + + SourceRange getParensRange() const { + return SourceRange(getLParenLoc(), getRParenLoc()); + } + void setParensRange(SourceRange range) { + setLParenLoc(range.getBegin()); + setRParenLoc(range.getEnd()); + } + + SourceRange getSourceRange() const { + return SourceRange(getTypeofLoc(), getRParenLoc()); + } + + void initializeLocal(SourceLocation Loc) { + setTypeofLoc(Loc); + setLParenLoc(Loc); + setRParenLoc(Loc); + } +}; + +class TypeOfExprTypeLoc : public TypeofLikeTypeLoc { +public: + Expr* getUnderlyingExpr() const { + return getTypePtr()->getUnderlyingExpr(); + } + // Reimplemented to account for GNU/C++ extension + // typeof unary-expression + // where there are no parentheses. + SourceRange getSourceRange() const; +}; + +class TypeOfTypeLoc + : public TypeofLikeTypeLoc { +public: + QualType getUnderlyingType() const { + return this->getTypePtr()->getUnderlyingType(); + } + TypeSourceInfo* getUnderlyingTInfo() const { + return this->getLocalData()->UnderlyingTInfo; + } + void setUnderlyingTInfo(TypeSourceInfo* TI) const { + this->getLocalData()->UnderlyingTInfo = TI; + } }; // FIXME: location of the 'decltype' and parens. diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Parse/DeclSpec.h index 06d0e4745a..6a3d8a924e 100644 --- a/include/clang/Parse/DeclSpec.h +++ b/include/clang/Parse/DeclSpec.h @@ -194,6 +194,7 @@ private: SourceLocation StorageClassSpecLoc, SCS_threadLoc; SourceLocation TSWLoc, TSCLoc, TSSLoc, TSTLoc; + SourceRange TypeofParensRange; SourceLocation TQ_constLoc, TQ_restrictLoc, TQ_volatileLoc; SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc; SourceLocation FriendLoc, ConstexprLoc; @@ -257,6 +258,9 @@ public: SourceLocation getTypeSpecSignLoc() const { return TSSLoc; } SourceLocation getTypeSpecTypeLoc() const { return TSTLoc; } + SourceRange getTypeofParensRange() const { return TypeofParensRange; } + void setTypeofParensRange(SourceRange range) { TypeofParensRange = range; } + /// getSpecifierName - Turn a type-specifier-type into a string like "_Bool" /// or "union". static const char *getSpecifierName(DeclSpec::TST T); diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp index 3ccb7a9cc6..0840c52b4c 100644 --- a/lib/AST/TypeLoc.cpp +++ b/lib/AST/TypeLoc.cpp @@ -13,6 +13,7 @@ #include "llvm/Support/raw_ostream.h" #include "clang/AST/TypeLocVisitor.h" +#include "clang/AST/Expr.h" using namespace clang; //===----------------------------------------------------------------------===// @@ -123,3 +124,14 @@ bool TypeSpecTypeLoc::classof(const TypeLoc *TL) { if (TL->getType().hasLocalQualifiers()) return false; return TSTChecker().Visit(*TL); } + +// Reimplemented to account for GNU/C++ extension +// typeof unary-expression +// where there are no parentheses. +SourceRange TypeOfExprTypeLoc::getSourceRange() const { + if (getRParenLoc().isValid()) + return SourceRange(getTypeofLoc(), getRParenLoc()); + else + return SourceRange(getTypeofLoc(), + getUnderlyingExpr()->getSourceRange().getEnd()); +} diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index 4c6e5f44a0..07d5a78bea 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -2111,10 +2111,15 @@ void TypeLocReader::VisitTypedefTypeLoc(TypedefTypeLoc TL) { TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); } void TypeLocReader::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) { - TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + TL.setTypeofLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + TL.setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + TL.setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); } void TypeLocReader::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) { - TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + TL.setTypeofLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + TL.setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + TL.setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + TL.setUnderlyingTInfo(Reader.GetTypeSourceInfo(Record, Idx)); } void TypeLocReader::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) { TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 84a8a450b0..3f6841b545 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -344,10 +344,15 @@ void TypeLocWriter::VisitTypedefTypeLoc(TypedefTypeLoc TL) { Writer.AddSourceLocation(TL.getNameLoc(), Record); } void TypeLocWriter::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) { - Writer.AddSourceLocation(TL.getNameLoc(), Record); + Writer.AddSourceLocation(TL.getTypeofLoc(), Record); + Writer.AddSourceLocation(TL.getLParenLoc(), Record); + Writer.AddSourceLocation(TL.getRParenLoc(), Record); } void TypeLocWriter::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) { - Writer.AddSourceLocation(TL.getNameLoc(), Record); + Writer.AddSourceLocation(TL.getTypeofLoc(), Record); + Writer.AddSourceLocation(TL.getLParenLoc(), Record); + Writer.AddSourceLocation(TL.getRParenLoc(), Record); + Writer.AddTypeSourceInfo(TL.getUnderlyingTInfo(), Record); } void TypeLocWriter::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) { Writer.AddSourceLocation(TL.getNameLoc(), Record); diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 1e8e33ebd8..66a6957443 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -3154,6 +3154,8 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) { Token OpTok = Tok; SourceLocation StartLoc = ConsumeToken(); + const bool hasParens = Tok.is(tok::l_paren); + bool isCastExpr; TypeTy *CastTy; SourceRange CastRange; @@ -3161,6 +3163,8 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) { isCastExpr, CastTy, CastRange); + if (hasParens) + DS.setTypeofParensRange(CastRange); if (CastRange.getEnd().isInvalid()) // FIXME: Not accurate, the range gets one token more than it should. diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 7c0460dbed..9515834bb8 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -1360,6 +1360,20 @@ namespace { cast(TInfo->getTypeLoc()); TL.copy(OldTL); } + void VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) { + assert(DS.getTypeSpecType() == DeclSpec::TST_typeofExpr); + TL.setTypeofLoc(DS.getTypeSpecTypeLoc()); + TL.setParensRange(DS.getTypeofParensRange()); + } + void VisitTypeOfTypeLoc(TypeOfTypeLoc TL) { + assert(DS.getTypeSpecType() == DeclSpec::TST_typeofType); + TL.setTypeofLoc(DS.getTypeSpecTypeLoc()); + TL.setParensRange(DS.getTypeofParensRange()); + assert(DS.getTypeRep()); + TypeSourceInfo *TInfo = 0; + Sema::GetTypeFromParser(DS.getTypeRep(), &TInfo); + TL.setUnderlyingTInfo(TInfo); + } void VisitTypeLoc(TypeLoc TL) { // FIXME: add other typespec types and change this to an assert. TL.initialize(DS.getTypeSpecTypeLoc()); diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index e966daa976..419dd9c00f 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -2619,18 +2619,16 @@ QualType TreeTransform::TransformTypedefType(TypeLocBuilder &TLB, template QualType TreeTransform::TransformTypeOfExprType(TypeLocBuilder &TLB, TypeOfExprTypeLoc TL) { - TypeOfExprType *T = TL.getTypePtr(); - // typeof expressions are not potentially evaluated contexts EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated); - Sema::OwningExprResult E = getDerived().TransformExpr(T->getUnderlyingExpr()); + Sema::OwningExprResult E = getDerived().TransformExpr(TL.getUnderlyingExpr()); if (E.isInvalid()) return QualType(); QualType Result = TL.getType(); if (getDerived().AlwaysRebuild() || - E.get() != T->getUnderlyingExpr()) { + E.get() != TL.getUnderlyingExpr()) { Result = getDerived().RebuildTypeOfExprType(move(E)); if (Result.isNull()) return QualType(); @@ -2638,7 +2636,9 @@ QualType TreeTransform::TransformTypeOfExprType(TypeLocBuilder &TLB, else E.take(); TypeOfExprTypeLoc NewTL = TLB.push(Result); - NewTL.setNameLoc(TL.getNameLoc()); + NewTL.setTypeofLoc(TL.getTypeofLoc()); + NewTL.setLParenLoc(TL.getLParenLoc()); + NewTL.setRParenLoc(TL.getRParenLoc()); return Result; } @@ -2646,23 +2646,23 @@ QualType TreeTransform::TransformTypeOfExprType(TypeLocBuilder &TLB, template QualType TreeTransform::TransformTypeOfType(TypeLocBuilder &TLB, TypeOfTypeLoc TL) { - TypeOfType *T = TL.getTypePtr(); - - // FIXME: should be an inner type, or at least have a TypeSourceInfo. - QualType Underlying = getDerived().TransformType(T->getUnderlyingType()); - if (Underlying.isNull()) + TypeSourceInfo* Old_Under_TI = TL.getUnderlyingTInfo(); + TypeSourceInfo* New_Under_TI = getDerived().TransformType(Old_Under_TI); + if (!New_Under_TI) return QualType(); QualType Result = TL.getType(); - if (getDerived().AlwaysRebuild() || - Underlying != T->getUnderlyingType()) { - Result = getDerived().RebuildTypeOfType(Underlying); + if (getDerived().AlwaysRebuild() || New_Under_TI != Old_Under_TI) { + Result = getDerived().RebuildTypeOfType(New_Under_TI->getType()); if (Result.isNull()) return QualType(); } TypeOfTypeLoc NewTL = TLB.push(Result); - NewTL.setNameLoc(TL.getNameLoc()); + NewTL.setTypeofLoc(TL.getTypeofLoc()); + NewTL.setLParenLoc(TL.getLParenLoc()); + NewTL.setRParenLoc(TL.getRParenLoc()); + NewTL.setUnderlyingTInfo(New_Under_TI); return Result; }