Skip to content

Commit

Permalink
Try to fix llvm#83802
Browse files Browse the repository at this point in the history
  • Loading branch information
vgvassilev committed Mar 5, 2024
1 parent 092b6c5 commit 4ee5a9b
Show file tree
Hide file tree
Showing 9 changed files with 61 additions and 22 deletions.
16 changes: 10 additions & 6 deletions clang/include/clang/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -4335,15 +4335,15 @@ class FileScopeAsmDecl : public Decl {
///
/// \note This is used in libInterpreter, clang -cc1 -fincremental-extensions
/// and in tools such as clang-repl.
class TopLevelStmtDecl : public Decl {
class TopLevelStmtDecl : public Decl, public DeclContext {
friend class ASTDeclReader;
friend class ASTDeclWriter;

Stmt *Statement = nullptr;
bool IsSemiMissing = false;

TopLevelStmtDecl(DeclContext *DC, SourceLocation L, Stmt *S)
: Decl(TopLevelStmt, DC, L), Statement(S) {}
: Decl(TopLevelStmt, DC, L), DeclContext(TopLevelStmt), Statement(S) {}

virtual void anchor();

Expand All @@ -4354,15 +4354,19 @@ class TopLevelStmtDecl : public Decl {
SourceRange getSourceRange() const override LLVM_READONLY;
Stmt *getStmt() { return Statement; }
const Stmt *getStmt() const { return Statement; }
void setStmt(Stmt *S) {
assert(IsSemiMissing && "Operation supported for printing values only!");
Statement = S;
}
void setStmt(Stmt *S);
bool isSemiMissing() const { return IsSemiMissing; }
void setSemiMissing(bool Missing = true) { IsSemiMissing = Missing; }

static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == TopLevelStmt; }

static DeclContext *castToDeclContext(const TopLevelStmtDecl *D) {
return static_cast<DeclContext *>(const_cast<TopLevelStmtDecl*>(D));
}
static TopLevelStmtDecl *castFromDeclContext(const DeclContext *DC) {
return static_cast<TopLevelStmtDecl *>(const_cast<DeclContext*>(DC));
}
};

/// Represents a block literal declaration, which is like an
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/AST/DeclBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -2005,6 +2005,7 @@ class DeclContext {
case Decl::Block:
case Decl::Captured:
case Decl::ObjCMethod:
case Decl::TopLevelStmt:
return true;
default:
return getDeclKind() >= Decl::firstFunction &&
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/DeclNodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ def LinkageSpec : DeclNode<Decl>, DeclContext;
def Export : DeclNode<Decl>, DeclContext;
def ObjCPropertyImpl : DeclNode<Decl>;
def FileScopeAsm : DeclNode<Decl>;
def TopLevelStmt : DeclNode<Decl>;
def TopLevelStmt : DeclNode<Decl>, DeclContext;
def AccessSpec : DeclNode<Decl>;
def Friend : DeclNode<Decl>;
def FriendTemplate : DeclNode<Decl>;
Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -3171,7 +3171,8 @@ class Sema final {
SourceLocation AsmLoc,
SourceLocation RParenLoc);

Decl *ActOnTopLevelStmtDecl(Stmt *Statement);
TopLevelStmtDecl *ActOnStartTopLevelStmtDecl(Scope *S);
void ActOnFinishTopLevelStmtDecl(TopLevelStmtDecl* D, Stmt *Statement);

/// Handle a C++11 empty-declaration and attribute-declaration.
Decl *ActOnEmptyDeclaration(Scope *S, const ParsedAttributesView &AttrList,
Expand Down
11 changes: 8 additions & 3 deletions clang/lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5404,14 +5404,13 @@ FileScopeAsmDecl *FileScopeAsmDecl::CreateDeserialized(ASTContext &C,
void TopLevelStmtDecl::anchor() {}

TopLevelStmtDecl *TopLevelStmtDecl::Create(ASTContext &C, Stmt *Statement) {
assert(Statement);
assert(C.getLangOpts().IncrementalExtensions &&
"Must be used only in incremental mode");

SourceLocation BeginLoc = Statement->getBeginLoc();
SourceLocation Loc = Statement ? Statement->getBeginLoc() : SourceLocation();
DeclContext *DC = C.getTranslationUnitDecl();

return new (C, DC) TopLevelStmtDecl(DC, BeginLoc, Statement);
return new (C, DC) TopLevelStmtDecl(DC, Loc, Statement);
}

TopLevelStmtDecl *TopLevelStmtDecl::CreateDeserialized(ASTContext &C,
Expand All @@ -5424,6 +5423,12 @@ SourceRange TopLevelStmtDecl::getSourceRange() const {
return SourceRange(getLocation(), Statement->getEndLoc());
}

void TopLevelStmtDecl::setStmt(Stmt *S) {
assert(S);
Statement = S;
setLocation(Statement->getBeginLoc());
}

void EmptyDecl::anchor() {}

EmptyDecl *EmptyDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) {
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/DeclBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1301,6 +1301,7 @@ DeclContext *DeclContext::getPrimaryContext() {
case Decl::ExternCContext:
case Decl::LinkageSpec:
case Decl::Export:
case Decl::TopLevelStmt:
case Decl::Block:
case Decl::Captured:
case Decl::OMPDeclareReduction:
Expand Down
24 changes: 16 additions & 8 deletions clang/lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5488,24 +5488,32 @@ Parser::DeclGroupPtrTy Parser::ParseTopLevelStmtDecl() {
// Parse a top-level-stmt.
Parser::StmtVector Stmts;
ParsedStmtContext SubStmtCtx = ParsedStmtContext();
Actions.PushFunctionScope();
ParseScope FnScope(this, Scope::FnScope | Scope::DeclScope |
Scope::CompoundStmtScope);
TopLevelStmtDecl *TLSD = Actions.ActOnStartTopLevelStmtDecl(getCurScope());
StmtResult R = ParseStatementOrDeclaration(Stmts, SubStmtCtx);
Actions.PopFunctionScopeInfo();
if (!R.isUsable())
return nullptr;

SmallVector<Decl *, 2> DeclsInGroup;
DeclsInGroup.push_back(Actions.ActOnTopLevelStmtDecl(R.get()));
Actions.ActOnFinishTopLevelStmtDecl(TLSD, R.get());

if (Tok.is(tok::annot_repl_input_end) &&
Tok.getAnnotationValue() != nullptr) {
ConsumeAnnotationToken();
cast<TopLevelStmtDecl>(DeclsInGroup.back())->setSemiMissing();
TLSD->setSemiMissing();
}

// Currently happens for things like -fms-extensions and use `__if_exists`.
for (Stmt *S : Stmts)
DeclsInGroup.push_back(Actions.ActOnTopLevelStmtDecl(S));
SmallVector<Decl *, 2> DeclsInGroup;
DeclsInGroup.push_back(TLSD);

// Currently happens for things like -fms-extensions and use `__if_exists`.
for (Stmt *S : Stmts) {
// Here we should be safe as `__if_exists` and friends are not introducing
// new variables which need to live outside file scope.
TopLevelStmtDecl *D = Actions.ActOnStartTopLevelStmtDecl(getCurScope());
Actions.ActOnFinishTopLevelStmtDecl(D, S);
DeclsInGroup.push_back(D);
}

return Actions.BuildDeclaratorGroup(DeclsInGroup);
}
Expand Down
15 changes: 12 additions & 3 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19949,12 +19949,21 @@ Decl *Sema::ActOnFileScopeAsmDecl(Expr *expr,
return New;
}

Decl *Sema::ActOnTopLevelStmtDecl(Stmt *Statement) {
auto *New = TopLevelStmtDecl::Create(Context, Statement);
Context.getTranslationUnitDecl()->addDecl(New);
TopLevelStmtDecl *Sema::ActOnStartTopLevelStmtDecl(Scope *S) {
auto *New = TopLevelStmtDecl::Create(Context, /*Statement=*/nullptr);
PushFunctionScope();
ActOnStartOfCompoundStmt(/*IsStmtExpr=*/false);
PushDeclContext(S, New);
return New;
}

void Sema::ActOnFinishTopLevelStmtDecl(TopLevelStmtDecl* D, Stmt *Statement) {
D->setStmt(Statement);
PopDeclContext();
ActOnFinishOfCompoundStmt();
PopFunctionScopeInfo();
}

void Sema::ActOnPragmaRedefineExtname(IdentifierInfo* Name,
IdentifierInfo* AliasName,
SourceLocation PragmaLoc,
Expand Down
10 changes: 10 additions & 0 deletions clang/test/Interpreter/execute-stmts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,13 @@ for (; i > 4; --i) { printf("i = %d\n", i); };

int j = i; printf("j = %d\n", j);
// CHECK-NEXT: j = 4

for(int i=0; i<2; i+=1) {};

for(int i=0; i<2; i+=1) ;

int a = 2;
for(int i=0; i<2; i+=1) a-=1;

int *aa=nullptr;
if (auto *b=aa) *b += 1;

0 comments on commit 4ee5a9b

Please sign in to comment.