aaron.ballman created this revision. aaron.ballman added a reviewer: rsmith. aaron.ballman added subscribers: cfe-commits, hintonda, alexfh.
We do not currently track the source locations for exception specifications such that their source range can be queried through the AST. This leads to trying to write more complex code to determine the source range for uses like FixItHints (see D18575 for an example). In addition to use within tools like clang-tidy, I think this information may become more important to track as exception specifications become more integrated into the type system. One thing this patch is missing is a test case. I'm not certain of the best way to test this functionality in isolation; suggestions welcome. http://reviews.llvm.org/D20428 Files: include/clang/AST/Decl.h include/clang/AST/TypeLoc.h lib/AST/Decl.cpp lib/Sema/SemaType.cpp lib/Sema/TreeTransform.h lib/Serialization/ASTReader.cpp lib/Serialization/ASTWriter.cpp
Index: lib/Serialization/ASTWriter.cpp =================================================================== --- lib/Serialization/ASTWriter.cpp +++ lib/Serialization/ASTWriter.cpp @@ -572,6 +572,7 @@ Record.AddSourceLocation(TL.getLocalRangeBegin()); Record.AddSourceLocation(TL.getLParenLoc()); Record.AddSourceLocation(TL.getRParenLoc()); + Record.AddSourceRange(TL.getExceptionSpecRange()); Record.AddSourceLocation(TL.getLocalRangeEnd()); for (unsigned i = 0, e = TL.getNumParams(); i != e; ++i) Record.AddDeclRef(TL.getParam(i)); Index: lib/Serialization/ASTReader.cpp =================================================================== --- lib/Serialization/ASTReader.cpp +++ lib/Serialization/ASTReader.cpp @@ -5812,6 +5812,8 @@ TL.setLocalRangeBegin(ReadSourceLocation(Record, Idx)); TL.setLParenLoc(ReadSourceLocation(Record, Idx)); TL.setRParenLoc(ReadSourceLocation(Record, Idx)); + TL.setExceptionSpecRange(SourceRange(ReadSourceLocation(Record, Idx), + ReadSourceLocation(Record, Idx))); TL.setLocalRangeEnd(ReadSourceLocation(Record, Idx)); for (unsigned i = 0, e = TL.getNumParams(); i != e; ++i) { TL.setParam(i, ReadDeclAs<ParmVarDecl>(Record, Idx)); Index: lib/Sema/TreeTransform.h =================================================================== --- lib/Sema/TreeTransform.h +++ lib/Sema/TreeTransform.h @@ -4919,6 +4919,7 @@ NewTL.setLocalRangeBegin(TL.getLocalRangeBegin()); NewTL.setLParenLoc(TL.getLParenLoc()); NewTL.setRParenLoc(TL.getRParenLoc()); + NewTL.setExceptionSpecRange(TL.getExceptionSpecRange()); NewTL.setLocalRangeEnd(TL.getLocalRangeEnd()); for (unsigned i = 0, e = NewTL.getNumParams(); i != e; ++i) NewTL.setParam(i, ParamDecls[i]); Index: lib/Sema/SemaType.cpp =================================================================== --- lib/Sema/SemaType.cpp +++ lib/Sema/SemaType.cpp @@ -5065,7 +5065,7 @@ ParmVarDecl *Param = cast<ParmVarDecl>(FTI.Params[i].Param); TL.setParam(tpi++, Param); } - // FIXME: exception specs + TL.setExceptionSpecRange(FTI.getExceptionSpecRange()); } void VisitParenTypeLoc(ParenTypeLoc TL) { assert(Chunk.Kind == DeclaratorChunk::Paren); Index: lib/AST/Decl.cpp =================================================================== --- lib/AST/Decl.cpp +++ lib/AST/Decl.cpp @@ -2935,6 +2935,18 @@ return RTRange; } +SourceRange FunctionDecl::getExceptionSpecSourceRange() const { + const TypeSourceInfo *TSI = getTypeSourceInfo(); + if (!TSI) + return SourceRange(); + FunctionTypeLoc FTL = + TSI->getTypeLoc().IgnoreParens().getAs<FunctionTypeLoc>(); + if (!FTL) + return SourceRange(); + + return FTL.getExceptionSpecRange(); +} + const Attr *FunctionDecl::getUnusedResultAttr() const { QualType RetType = getReturnType(); if (RetType->isRecordType()) { Index: include/clang/AST/TypeLoc.h =================================================================== --- include/clang/AST/TypeLoc.h +++ include/clang/AST/TypeLoc.h @@ -1248,6 +1248,7 @@ SourceLocation LocalRangeBegin; SourceLocation LParenLoc; SourceLocation RParenLoc; + SourceRange ExceptionSpecRange; SourceLocation LocalRangeEnd; }; @@ -1289,6 +1290,13 @@ return SourceRange(getLParenLoc(), getRParenLoc()); } + SourceRange getExceptionSpecRange() const { + return this->getLocalData()->ExceptionSpecRange; + } + void setExceptionSpecRange(SourceRange R) { + this->getLocalData()->ExceptionSpecRange = R; + } + ArrayRef<ParmVarDecl *> getParams() const { return llvm::makeArrayRef(getParmArray(), getNumParams()); } @@ -1318,6 +1326,7 @@ setLocalRangeBegin(Loc); setLParenLoc(Loc); setRParenLoc(Loc); + setExceptionSpecRange(SourceRange(Loc)); setLocalRangeEnd(Loc); for (unsigned i = 0, e = getNumParams(); i != e; ++i) setParam(i, nullptr); Index: include/clang/AST/Decl.h =================================================================== --- include/clang/AST/Decl.h +++ include/clang/AST/Decl.h @@ -2019,6 +2019,10 @@ /// limited representation in the AST. SourceRange getReturnTypeSourceRange() const; + /// \brief Attempt to compute an informative source range covering the + /// function exception specification, if any. + SourceRange getExceptionSpecSourceRange() const; + /// \brief Determine the type of an expression that calls this function. QualType getCallResultType() const { assert(getType()->getAs<FunctionType>() && "Expected a FunctionType!");
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits