diff options
author | Eduardo Caldas <ecaldas@google.com> | 2020-06-15 17:08:39 +0000 |
---|---|---|
committer | Eduardo Caldas <ecaldas@google.com> | 2020-07-10 16:21:11 +0000 |
commit | f33c2c27a8d4ea831aa7c2c2649066be91318d85 (patch) | |
tree | 1824386289595d9de6ec3af9dc83c83e01612a3b /clang/lib/Tooling/Syntax/BuildTree.cpp | |
parent | e5123ea248eb460c6695dc28ed2f1cc53495356b (diff) | |
download | llvm-f33c2c27a8d4ea831aa7c2c2649066be91318d85.zip llvm-f33c2c27a8d4ea831aa7c2c2649066be91318d85.tar.gz llvm-f33c2c27a8d4ea831aa7c2c2649066be91318d85.tar.bz2 |
Fix crash on `user defined literals`
Summary:
Given an UserDefinedLiteral `1.2_w`:
Problem: Lexer generates one Token for the literal, but ClangAST
references two source locations
Fix: Ignore the operator and interpret it as the underlying literal.
e.g.: `1.2_w` token generates syntax node IntegerLiteral(1.2_w)
Subscribers: cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D82157
Diffstat (limited to 'clang/lib/Tooling/Syntax/BuildTree.cpp')
-rw-r--r-- | clang/lib/Tooling/Syntax/BuildTree.cpp | 45 |
1 files changed, 41 insertions, 4 deletions
diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp index f9fdf47..8204d3f 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -216,7 +216,8 @@ static SourceRange getDeclaratorRange(const SourceManager &SM, TypeLoc T, } if (Initializer.isValid()) { auto InitializerEnd = Initializer.getEnd(); - assert(SM.isBeforeInTranslationUnit(End, InitializerEnd) || End == InitializerEnd); + assert(SM.isBeforeInTranslationUnit(End, InitializerEnd) || + End == InitializerEnd); End = InitializerEnd; } return SourceRange(Start, End); @@ -708,6 +709,42 @@ public: return NNS; } + bool TraverseUserDefinedLiteral(UserDefinedLiteral *S) { + // The semantic AST node `UserDefinedLiteral` (UDL) may have one child node + // referencing the location of the UDL suffix (`_w` in `1.2_w`). The + // UDL suffix location does not point to the beginning of a token, so we + // can't represent the UDL suffix as a separate syntax tree node. + + return WalkUpFromUserDefinedLiteral(S); + } + + syntax::NodeKind getUserDefinedLiteralKind(UserDefinedLiteral *S) { + switch (S->getLiteralOperatorKind()) { + case clang::UserDefinedLiteral::LOK_Integer: + return syntax::NodeKind::IntegerUserDefinedLiteralExpression; + case clang::UserDefinedLiteral::LOK_Floating: + return syntax::NodeKind::FloatUserDefinedLiteralExpression; + case clang::UserDefinedLiteral::LOK_Character: + return syntax::NodeKind::CharUserDefinedLiteralExpression; + case clang::UserDefinedLiteral::LOK_String: + return syntax::NodeKind::StringUserDefinedLiteralExpression; + case clang::UserDefinedLiteral::LOK_Raw: + case clang::UserDefinedLiteral::LOK_Template: + // FIXME: Apply `NumericLiteralParser` to the underlying token to deduce + // the right UDL kind. That would require a `Preprocessor` though. + return syntax::NodeKind::UnknownUserDefinedLiteralExpression; + } + } + + bool WalkUpFromUserDefinedLiteral(UserDefinedLiteral *S) { + Builder.markChildToken(S->getBeginLoc(), syntax::NodeRole::LiteralToken); + Builder.foldNode(Builder.getExprRange(S), + new (allocator()) syntax::UserDefinedLiteralExpression( + getUserDefinedLiteralKind(S)), + S); + return true; + } + bool WalkUpFromDeclRefExpr(DeclRefExpr *S) { if (auto *NNS = BuildNestedNameSpecifier(S->getQualifierLoc())) Builder.markChild(NNS, syntax::NodeRole::IdExpression_qualifier); @@ -817,9 +854,9 @@ public: bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *S) { if (getOperatorNodeKind(*S) == syntax::NodeKind::PostfixUnaryOperatorExpression) { - // A postfix unary operator is declared as taking two operands. The second - // operand is used to distinguish from its prefix counterpart. In the - // semantic AST this "phantom" operand is represented as a + // A postfix unary operator is declared as taking two operands. The + // second operand is used to distinguish from its prefix counterpart. In + // the semantic AST this "phantom" operand is represented as a // `IntegerLiteral` with invalid `SourceLocation`. We skip visiting this // operand because it does not correspond to anything written in source // code |