From 4aa88f8d8469ced8fe04a0c411bbccc5d313e055 Mon Sep 17 00:00:00 2001 From: Steve Naroff Date: Thu, 19 Jul 2007 01:06:55 +0000 Subject: [PATCH] Work towards fixing crasher with compound literals... Before this commit, we crashed in ParseBinOp... [dylan:~/llvm/tools/clang] admin% ../../Debug/bin/clang -parse-ast-check compound_literal.c SemaExpr.cpp:1298: failed assertion `(rhs != 0) && "ParseBinOp(): missing right expression"' With this commit, we still crash in the newly added action ParseCompoundLiteral (which is progress:-) [dylan:~/llvm/tools/clang] admin% ../../Debug/bin/clang -parse-ast-check compound_literal.c SemaExpr.cpp:478: failed assertion `(Op != 0) && "ParseCompoundLiteral(): missing expression"' The crash go away once the actions return AST nodes. I will do this in a separate commit. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@40032 91177308-0d34-0410-b5e6-96231b3b80d8 --- Parse/ParseExpr.cpp | 3 +- Parse/ParseInit.cpp | 63 ++++++++++++++++++++-------------- Sema/Sema.h | 7 ++++ Sema/SemaExpr.cpp | 22 ++++++++++++ include/clang/Parse/Action.h | 9 +++++ test/Parser/compound_literal.c | 5 +++ 6 files changed, 82 insertions(+), 27 deletions(-) create mode 100644 test/Parser/compound_literal.c diff --git a/Parse/ParseExpr.cpp b/Parse/ParseExpr.cpp index 41f347f9aa..5862e7bd84 100644 --- a/Parse/ParseExpr.cpp +++ b/Parse/ParseExpr.cpp @@ -880,7 +880,8 @@ Parser::ExprResult Parser::ParseParenExpression(ParenParseOption &ExprType, Diag(OpenLoc, diag::ext_c99_compound_literal); Result = ParseInitializer(); ExprType = CompoundLiteral; - // TODO: Build AST for compound literal. + if (!Result.isInvalid) + return Actions.ParseCompoundLiteral(OpenLoc, Ty, RParenLoc, Result.Val); } else if (ExprType == CastExpr) { // Note that this doesn't parse the subsequence cast-expression, it just // returns the parsed type to the callee. diff --git a/Parse/ParseInit.cpp b/Parse/ParseInit.cpp index 01169d8859..75e1c7356e 100644 --- a/Parse/ParseInit.cpp +++ b/Parse/ParseInit.cpp @@ -13,6 +13,7 @@ #include "clang/Parse/Parser.h" #include "clang/Basic/Diagnostic.h" +#include "llvm/ADT/SmallString.h" using namespace clang; @@ -152,37 +153,47 @@ Parser::ExprResult Parser::ParseInitializer() { // We support empty initializers, but tell the user that they aren't using // C99-clean code. - if (Tok.getKind() == tok::r_brace) + if (Tok.getKind() == tok::r_brace) { Diag(LBraceLoc, diag::ext_gnu_empty_initializer); - else { - while (1) { - // Parse: designation[opt] initializer - - // If we know that this cannot be a designation, just parse the nested - // initializer directly. - ExprResult SubElt; - if (!MayBeDesignationStart(Tok.getKind())) - SubElt = ParseInitializer(); - else - SubElt = ParseInitializerWithPotentialDesignator(); - - // If we couldn't parse the subelement, bail out. - if (SubElt.isInvalid) { - SkipUntil(tok::r_brace); - return SubElt; - } + // Match the '}'. + return Actions.ParseInitList(LBraceLoc, 0, 0, ConsumeBrace()); + } + llvm::SmallVector InitExprs; + bool InitExprsOk = true; + + while (1) { + // Parse: designation[opt] initializer - // If we don't have a comma continued list, we're done. - if (Tok.getKind() != tok::comma) break; - ConsumeToken(); + // If we know that this cannot be a designation, just parse the nested + // initializer directly. + ExprResult SubElt; + if (!MayBeDesignationStart(Tok.getKind())) + SubElt = ParseInitializer(); + else + SubElt = ParseInitializerWithPotentialDesignator(); + + // If we couldn't parse the subelement, bail out. + if (SubElt.isInvalid) { + InitExprsOk = false; + SkipUntil(tok::r_brace); + break; + } else + InitExprs.push_back(SubElt.Val); - // Handle trailing comma. - if (Tok.getKind() == tok::r_brace) break; - } + // If we don't have a comma continued list, we're done. + if (Tok.getKind() != tok::comma) break; + + // FIXME: save comma locations. + ConsumeToken(); + + // Handle trailing comma. + if (Tok.getKind() == tok::r_brace) break; } - + if (InitExprsOk && Tok.getKind() == tok::r_brace) + return Actions.ParseInitList(LBraceLoc, &InitExprs[0], InitExprs.size(), + ConsumeBrace()); // Match the '}'. MatchRHSPunctuation(tok::r_brace, LBraceLoc); - return ExprResult(false); + return ExprResult(true); // an error occurred. } diff --git a/Sema/Sema.h b/Sema/Sema.h index f87cee60a9..0feddd3b15 100644 --- a/Sema/Sema.h +++ b/Sema/Sema.h @@ -245,7 +245,14 @@ public: virtual ExprResult ParseCastExpr(SourceLocation LParenLoc, TypeTy *Ty, SourceLocation RParenLoc, ExprTy *Op); + + virtual ExprResult ParseCompoundLiteral(SourceLocation LParenLoc, TypeTy *Ty, + SourceLocation RParenLoc, ExprTy *Op); + virtual ExprResult ParseInitList(SourceLocation LParenLoc, + ExprTy **InitList, unsigned NumInit, + SourceLocation RParenLoc); + virtual ExprResult ParseBinOp(SourceLocation TokLoc, tok::TokenKind Kind, ExprTy *LHS,ExprTy *RHS); diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp index 044fb63bf0..999f29a8ae 100644 --- a/Sema/SemaExpr.cpp +++ b/Sema/SemaExpr.cpp @@ -470,6 +470,28 @@ ParseCallExpr(ExprTy *Fn, SourceLocation LParenLoc, RParenLoc); } +Action::ExprResult Sema:: +ParseCompoundLiteral(SourceLocation LParenLoc, TypeTy *Ty, + SourceLocation RParenLoc, ExprTy *Op) { + assert((Ty != 0) && "ParseCompoundLiteral(): missing type"); + QualType literalType = QualType::getFromOpaquePtr(Ty); + assert((Op != 0) && "ParseCompoundLiteral(): missing expression"); + Expr *literalExpr = static_cast(Op); + + // FIXME: add semantic analysis (C99 6.5.2.5). + return false; // FIXME: instantiate a CompoundLiteralExpr +} + +Action::ExprResult Sema:: +ParseInitList(SourceLocation LParenLoc, ExprTy **InitList, unsigned NumInit, + SourceLocation RParenLoc) { + // FIXME: add semantic analysis (C99 6.7.8). This involves + // knowledge of the object being intialized. As a result, the code for + // doing the semantic analysis will likely be located elsewhere (i.e. in + // consumers of InitListExpr (e.g. ParseDeclarator, ParseCompoundLiteral). + return false; // FIXME instantiate an InitListExpr. +} + Action::ExprResult Sema:: ParseCastExpr(SourceLocation LParenLoc, TypeTy *Ty, SourceLocation RParenLoc, ExprTy *Op) { diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index bf5499a081..4922c9a463 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -332,6 +332,15 @@ public: return 0; } + virtual ExprResult ParseCompoundLiteral(SourceLocation LParen, TypeTy *Ty, + SourceLocation RParen, ExprTy *Op) { + return 0; + } + virtual ExprResult ParseInitList(SourceLocation LParenLoc, + ExprTy **InitList, unsigned NumInit, + SourceLocation RParenLoc) { + return 0; + } virtual ExprResult ParseCastExpr(SourceLocation LParenLoc, TypeTy *Ty, SourceLocation RParenLoc, ExprTy *Op) { return 0; diff --git a/test/Parser/compound_literal.c b/test/Parser/compound_literal.c new file mode 100644 index 0000000000..ef4576d18f --- /dev/null +++ b/test/Parser/compound_literal.c @@ -0,0 +1,5 @@ +// RUN: clang -parse-ast-check %s +int main() { + char *s; + s = (char []){"whatever"}; +} -- 2.40.0