r291771 - Tracking exception specification source locations
Malcolm Parsons via cfe-commits
cfe-commits at lists.llvm.org
Thu Jan 12 08:11:28 PST 2017
Author: malcolm.parsons
Date: Thu Jan 12 10:11:28 2017
New Revision: 291771
URL: http://llvm.org/viewvc/llvm-project?rev=291771&view=rev
Log:
Tracking exception specification source locations
Summary:
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.
Patch by Don Hinton.
Reviewers: rsmith
Subscribers: malcolm.parsons, sbarzowski, alexfh, hintonda, cfe-commits
Differential Revision: https://reviews.llvm.org/D20428
Modified:
cfe/trunk/include/clang/AST/Decl.h
cfe/trunk/include/clang/AST/TypeLoc.h
cfe/trunk/lib/AST/Decl.cpp
cfe/trunk/lib/Parse/ParseDeclCXX.cpp
cfe/trunk/lib/Sema/SemaType.cpp
cfe/trunk/lib/Sema/TreeTransform.h
cfe/trunk/lib/Serialization/ASTReader.cpp
cfe/trunk/lib/Serialization/ASTWriter.cpp
cfe/trunk/unittests/AST/SourceLocationTest.cpp
Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=291771&r1=291770&r2=291771&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Thu Jan 12 10:11:28 2017
@@ -2061,6 +2061,10 @@ public:
/// 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!");
Modified: cfe/trunk/include/clang/AST/TypeLoc.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TypeLoc.h?rev=291771&r1=291770&r2=291771&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/TypeLoc.h (original)
+++ cfe/trunk/include/clang/AST/TypeLoc.h Thu Jan 12 10:11:28 2017
@@ -1351,6 +1351,19 @@ class FunctionTypeLoc : public ConcreteT
FunctionTypeLoc,
FunctionType,
FunctionLocInfo> {
+ bool hasExceptionSpec() const {
+ if (auto *FPT = dyn_cast<FunctionProtoType>(getTypePtr())) {
+ return FPT->hasExceptionSpec();
+ }
+ return false;
+ }
+
+ SourceRange *getExceptionSpecRangePtr() const {
+ assert(hasExceptionSpec() && "No exception spec range");
+ // After the Info comes the ParmVarDecl array, and after that comes the
+ // exception specification information.
+ return (SourceRange *)(getParmArray() + getNumParams());
+ }
public:
SourceLocation getLocalRangeBegin() const {
return getLocalData()->LocalRangeBegin;
@@ -1384,6 +1397,16 @@ public:
return SourceRange(getLParenLoc(), getRParenLoc());
}
+ SourceRange getExceptionSpecRange() const {
+ if (hasExceptionSpec())
+ return *getExceptionSpecRangePtr();
+ return SourceRange();
+ }
+ void setExceptionSpecRange(SourceRange R) {
+ if (hasExceptionSpec())
+ *getExceptionSpecRangePtr() = R;
+ }
+
ArrayRef<ParmVarDecl *> getParams() const {
return llvm::makeArrayRef(getParmArray(), getNumParams());
}
@@ -1416,12 +1439,15 @@ public:
setLocalRangeEnd(Loc);
for (unsigned i = 0, e = getNumParams(); i != e; ++i)
setParam(i, nullptr);
+ if (hasExceptionSpec())
+ setExceptionSpecRange(Loc);
}
/// \brief Returns the size of the type source info data block that is
/// specific to this type.
unsigned getExtraLocalDataSize() const {
- return getNumParams() * sizeof(ParmVarDecl *);
+ unsigned ExceptSpecSize = hasExceptionSpec() ? sizeof(SourceRange) : 0;
+ return (getNumParams() * sizeof(ParmVarDecl *)) + ExceptSpecSize;
}
unsigned getExtraLocalDataAlignment() const { return alignof(ParmVarDecl *); }
Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=291771&r1=291770&r2=291771&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Thu Jan 12 10:11:28 2017
@@ -2990,6 +2990,18 @@ SourceRange FunctionDecl::getReturnTypeS
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()) {
Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=291771&r1=291770&r2=291771&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Thu Jan 12 10:11:28 2017
@@ -3544,7 +3544,7 @@ Parser::tryParseExceptionSpecification(b
Actions.CheckBooleanCondition(KeywordLoc, NoexceptExpr.get());
NoexceptRange = SourceRange(KeywordLoc, T.getCloseLocation());
} else {
- NoexceptType = EST_None;
+ NoexceptType = EST_BasicNoexcept;
}
} else {
// There is no argument.
Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=291771&r1=291770&r2=291771&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Thu Jan 12 10:11:28 2017
@@ -5263,7 +5263,7 @@ namespace {
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);
Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=291771&r1=291770&r2=291771&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Thu Jan 12 10:11:28 2017
@@ -5023,6 +5023,7 @@ QualType TreeTransform<Derived>::Transfo
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]);
Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=291771&r1=291770&r2=291771&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Thu Jan 12 10:11:28 2017
@@ -5990,6 +5990,8 @@ void TypeLocReader::VisitFunctionTypeLoc
TL.setLocalRangeBegin(ReadSourceLocation());
TL.setLParenLoc(ReadSourceLocation());
TL.setRParenLoc(ReadSourceLocation());
+ TL.setExceptionSpecRange(SourceRange(Reader->ReadSourceLocation(*F, Record, Idx),
+ Reader->ReadSourceLocation(*F, Record, Idx)));
TL.setLocalRangeEnd(ReadSourceLocation());
for (unsigned i = 0, e = TL.getNumParams(); i != e; ++i) {
TL.setParam(i, Reader->ReadDeclAs<ParmVarDecl>(*F, Record, Idx));
Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=291771&r1=291770&r2=291771&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Thu Jan 12 10:11:28 2017
@@ -629,6 +629,7 @@ void TypeLocWriter::VisitFunctionTypeLoc
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));
Modified: cfe/trunk/unittests/AST/SourceLocationTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/SourceLocationTest.cpp?rev=291771&r1=291770&r2=291771&view=diff
==============================================================================
--- cfe/trunk/unittests/AST/SourceLocationTest.cpp (original)
+++ cfe/trunk/unittests/AST/SourceLocationTest.cpp Thu Jan 12 10:11:28 2017
@@ -670,5 +670,72 @@ TEST(CXXMethodDecl, CXXMethodDeclWithNoE
Language::Lang_CXX11));
}
+class ExceptionSpecRangeVerifier : public RangeVerifier<TypeLoc> {
+protected:
+ SourceRange getRange(const TypeLoc &Node) override {
+ auto T =
+ Node.getUnqualifiedLoc().castAs<FunctionProtoTypeLoc>();
+ assert(!T.isNull());
+ return T.getExceptionSpecRange();
+ }
+};
+
+class ParmVarExceptionSpecRangeVerifier : public RangeVerifier<ParmVarDecl> {
+protected:
+ SourceRange getRange(const ParmVarDecl &Node) override {
+ if (const TypeSourceInfo *TSI = Node.getTypeSourceInfo()) {
+ TypeLoc TL = TSI->getTypeLoc();
+ if (TL.getType()->isPointerType()) {
+ TL = TL.getNextTypeLoc().IgnoreParens();
+ if (auto FPTL = TL.getAs<FunctionProtoTypeLoc>()) {
+ return FPTL.getExceptionSpecRange();
+ }
+ }
+ }
+ return SourceRange();
+ }
+};
+
+TEST(FunctionDecl, ExceptionSpecifications) {
+ ExceptionSpecRangeVerifier Verifier;
+
+ Verifier.expectRange(1, 10, 1, 16);
+ EXPECT_TRUE(Verifier.match("void f() throw();\n", loc(functionType())));
+
+ Verifier.expectRange(1, 10, 1, 34);
+ EXPECT_TRUE(Verifier.match("void f() throw(void(void) throw());\n",
+ loc(functionType())));
+
+ Verifier.expectRange(1, 10, 1, 19);
+ std::vector<std::string> Args;
+ Args.push_back("-fms-extensions");
+ EXPECT_TRUE(Verifier.match("void f() throw(...);\n", loc(functionType()),
+ Args, Language::Lang_CXX));
+
+ Verifier.expectRange(1, 10, 1, 10);
+ EXPECT_TRUE(Verifier.match("void f() noexcept;\n", loc(functionType()),
+ Language::Lang_CXX11));
+
+ Verifier.expectRange(1, 10, 1, 24);
+ EXPECT_TRUE(Verifier.match("void f() noexcept(false);\n", loc(functionType()),
+ Language::Lang_CXX11));
+
+ Verifier.expectRange(1, 10, 1, 32);
+ EXPECT_TRUE(Verifier.match("void f() noexcept(noexcept(1+1));\n",
+ loc(functionType()), Language::Lang_CXX11));
+
+ ParmVarExceptionSpecRangeVerifier Verifier2;
+ Verifier2.expectRange(1, 25, 1, 31);
+ EXPECT_TRUE(Verifier2.match("void g(void (*fp)(void) throw());\n",
+ parmVarDecl(hasType(pointerType(pointee(
+ parenType(innerType(functionType()))))))));
+
+ Verifier2.expectRange(1, 25, 1, 38);
+ EXPECT_TRUE(Verifier2.match("void g(void (*fp)(void) noexcept(true));\n",
+ parmVarDecl(hasType(pointerType(pointee(
+ parenType(innerType(functionType())))))),
+ Language::Lang_CXX11));
+}
+
} // end namespace ast_matchers
} // end namespace clang
More information about the cfe-commits
mailing list