-
Notifications
You must be signed in to change notification settings - Fork 10.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Issue #63106: [сlang] Representation of ellipsis in AST #80976
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-clang Author: Shahid Iqbal (shahidiqbal13) Changes
Output of the fixed 1st issue (catch(...))
Full diff: https://github.com/llvm/llvm-project/pull/80976.diff 7 Files Affected:
diff --git a/clang/NOTES.txt b/clang/NOTES.txt
index f06ea8c70cd34..c83dda52a1fc2 100644
--- a/clang/NOTES.txt
+++ b/clang/NOTES.txt
@@ -4,6 +4,8 @@
//===---------------------------------------------------------------------===//
+//TESTING git infra//
+
To time GCC preprocessing speed without output, use:
"time gcc -MM file"
This is similar to -Eonly.
diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h
index 5b1038582bc67..67f5c7dd1b7f9 100644
--- a/clang/include/clang/AST/DeclBase.h
+++ b/clang/include/clang/AST/DeclBase.h
@@ -301,6 +301,9 @@ class alignas(8) Decl {
LLVM_PREFERRED_TYPE(bool)
unsigned Implicit : 1;
+ LLVM_PREFERRED_TYPE(bool)
+ unsigned HasCatchEllipsis : 1;
+
/// Whether this declaration was "used", meaning that a definition is
/// required.
LLVM_PREFERRED_TYPE(bool)
@@ -394,7 +397,7 @@ class alignas(8) Decl {
Decl(Kind DK, DeclContext *DC, SourceLocation L)
: NextInContextAndBits(nullptr, getModuleOwnershipKindForChildOf(DC)),
DeclCtx(DC), Loc(L), DeclKind(DK), InvalidDecl(false), HasAttrs(false),
- Implicit(false), Used(false), Referenced(false),
+ Implicit(false), HasCatchEllipsis(false), Used(false), Referenced(false),
TopLevelDeclInObjCContainer(false), Access(AS_none), FromASTFile(0),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
CacheValidAndLinkage(llvm::to_underlying(Linkage::Invalid)) {
@@ -402,7 +405,7 @@ class alignas(8) Decl {
}
Decl(Kind DK, EmptyShell Empty)
- : DeclKind(DK), InvalidDecl(false), HasAttrs(false), Implicit(false),
+ : DeclKind(DK), InvalidDecl(false), HasAttrs(false), Implicit(false), HasCatchEllipsis(false),
Used(false), Referenced(false), TopLevelDeclInObjCContainer(false),
Access(AS_none), FromASTFile(0),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
@@ -597,6 +600,10 @@ class alignas(8) Decl {
bool isImplicit() const { return Implicit; }
void setImplicit(bool I = true) { Implicit = I; }
+ /// isCatchEllipsisTok - Indicates whether '...' is present in the catch decl
+ bool isCatchEllipsisTok() const { return HasCatchEllipsis; }
+ void setCatchEllipsisTok(bool I = true) { HasCatchEllipsis = I; }
+
/// Whether *any* (re-)declaration of the entity was used, meaning that
/// a definition is required.
///
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 501dc01200a1c..ffc6d2926f85f 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5322,7 +5322,7 @@ class Sema final {
SourceLocation IdLoc,
IdentifierInfo *Id);
- Decl *ActOnExceptionDeclarator(Scope *S, Declarator &D);
+ Decl *ActOnExceptionDeclarator(Scope *S, Declarator &D, bool isCatchAll = false);
StmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc,
Decl *ExDecl, Stmt *HandlerBlock);
diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp
index e8274fcd5cfe9..1da20cdfa36a6 100644
--- a/clang/lib/AST/TextNodeDumper.cpp
+++ b/clang/lib/AST/TextNodeDumper.cpp
@@ -272,6 +272,9 @@ void TextNodeDumper::Visit(const Decl *D) {
if (D->isImplicit())
OS << " implicit";
+ if (D->isCatchEllipsisTok())
+ OS << " catch_all ";
+
if (D->isUsed())
OS << " used";
else if (D->isThisDeclarationReferenced())
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 2531147c23196..56c1e86afd481 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -2698,9 +2698,17 @@ StmtResult Parser::ParseCXXCatchBlock(bool FnCatch) {
Declarator ExDecl(DS, Attributes, DeclaratorContext::CXXCatch);
ParseDeclarator(ExDecl);
ExceptionDecl = Actions.ActOnExceptionDeclarator(getCurScope(), ExDecl);
- } else
- ConsumeToken();
-
+ }
+ else {
+ ConsumeToken();
+ // explicitly creating a var of type no-type for '...' and marking it as catch_all
+ ParsedAttributes Attributes(AttrFactory);
+ DeclSpec DS(AttrFactory);
+ Declarator ExDecl(DS, Attributes, DeclaratorContext::BlockLiteral);
+ ParseDeclarator(ExDecl);
+ ExceptionDecl = Actions.ActOnExceptionDeclarator(getCurScope(), ExDecl, true);
+ ExceptionDecl->setCatchEllipsisTok();
+ }
T.consumeClose();
if (T.getCloseLocation().isInvalid())
return StmtError();
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 3688192e6cbe5..1916d3c3d8ebd 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -16983,7 +16983,7 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S,
/// ActOnExceptionDeclarator - Parsed the exception-declarator in a C++ catch
/// handler.
-Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) {
+Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D, bool isCatchAll) {
TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
bool Invalid = D.isInvalidType();
@@ -16994,6 +16994,9 @@ Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) {
D.getIdentifierLoc());
Invalid = true;
}
+ if (isCatchAll)
+ TInfo = Context.getTrivialTypeSourceInfo(Context.UnknownAnyTy,
+ D.getIdentifierLoc());
IdentifierInfo *II = D.getIdentifier();
if (NamedDecl *PrevDecl = LookupSingleName(S, II, D.getIdentifierLoc(),
@@ -17021,7 +17024,7 @@ Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) {
VarDecl *ExDecl = BuildExceptionDeclaration(
S, TInfo, D.getBeginLoc(), D.getIdentifierLoc(), D.getIdentifier());
- if (Invalid)
+ if (Invalid && !isCatchAll)
ExDecl->setInvalidDecl();
// Add the exception declaration into this scope.
diff --git a/clang/test/AST/ast-dump-stmt.cpp b/clang/test/AST/ast-dump-stmt.cpp
index 407584e5b82de..a5a7e9d535c1d 100644
--- a/clang/test/AST/ast-dump-stmt.cpp
+++ b/clang/test/AST/ast-dump-stmt.cpp
@@ -41,7 +41,7 @@ void TestCatch2() {
try {
}
// CHECK-NEXT: CXXCatchStmt
-// CHECK-NEXT: NULL
+// CHECK-NEXT: VarDecl {{.*}} '<unknown type>'
// CHECK-NEXT: CompoundStmt
catch (...) {
}
|
You can test this locally with the following command:git-clang-format --diff ec42d547eba5c0ad0bddbecc8902d35383968e78 87d105ac46dfbfdc6a21688069d95425da3443c3 -- clang/include/clang/AST/Decl.h clang/include/clang/Sema/Sema.h clang/lib/AST/JSONNodeDumper.cpp clang/lib/AST/TextNodeDumper.cpp clang/lib/Parse/ParseStmt.cpp clang/lib/Sema/SemaDeclCXX.cpp clang/test/AST/ast-dump-stmt-json.cpp clang/test/AST/ast-dump-stmt.cpp View the diff from clang-format here.diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index d6e22ce6c46..e6af9d0d74d 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -1487,7 +1487,6 @@ public:
NonParmVarDeclBits.EllipsisVar = EV;
}
-
/// Determine whether this local variable can be used with the named
/// return value optimization (NRVO).
///
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index ffc6d2926f8..0f9418e329e 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5322,7 +5322,8 @@ public:
SourceLocation IdLoc,
IdentifierInfo *Id);
- Decl *ActOnExceptionDeclarator(Scope *S, Declarator &D, bool isCatchAll = false);
+ Decl *ActOnExceptionDeclarator(Scope *S, Declarator &D,
+ bool isCatchAll = false);
StmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc,
Decl *ExDecl, Stmt *HandlerBlock);
diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp
index 2a03ad30dd3..9c092d11cee 100644
--- a/clang/lib/AST/JSONNodeDumper.cpp
+++ b/clang/lib/AST/JSONNodeDumper.cpp
@@ -116,8 +116,8 @@ void JSONNodeDumper::Visit(const Decl *D) {
JOS.attribute("isReferenced", true);
if (const VarDecl *ND = dyn_cast<VarDecl>(D))
- if (ND->isEllipsisVariable())
- JOS.attribute("catch_all", true);
+ if (ND->isEllipsisVariable())
+ JOS.attribute("catch_all", true);
if (const auto *ND = dyn_cast<NamedDecl>(D))
attributeOnlyIfTrue("isHidden", !ND->isUnconditionallyVisible());
diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp
index 056ea399d7e..8ffd6119db5 100644
--- a/clang/lib/AST/TextNodeDumper.cpp
+++ b/clang/lib/AST/TextNodeDumper.cpp
@@ -272,8 +272,8 @@ void TextNodeDumper::Visit(const Decl *D) {
if (D->isImplicit())
OS << " implicit";
if (const VarDecl *ND = dyn_cast<VarDecl>(D))
- if (ND->isEllipsisVariable())
- OS << " catch_all";
+ if (ND->isEllipsisVariable())
+ OS << " catch_all";
if (D->isUsed())
OS << " used";
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 83f2d451486..3d7d50f0435 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -2698,15 +2698,16 @@ StmtResult Parser::ParseCXXCatchBlock(bool FnCatch) {
Declarator ExDecl(DS, Attributes, DeclaratorContext::CXXCatch);
ParseDeclarator(ExDecl);
ExceptionDecl = Actions.ActOnExceptionDeclarator(getCurScope(), ExDecl);
- }
- else {
- CatchLoc = ConsumeToken();
- // explicitly creating a var of type no-type for '...' and marking it as catch_all
- ParsedAttributes Attributes(AttrFactory);
- DeclSpec DS(AttrFactory);
- Declarator ExDecl(DS, Attributes, DeclaratorContext::BlockLiteral);
- ParseDeclarator(ExDecl);
- ExceptionDecl = Actions.ActOnExceptionDeclarator(getCurScope(), ExDecl, true);
+ } else {
+ CatchLoc = ConsumeToken();
+ // explicitly creating a var of type no-type for '...' and marking it as
+ // catch_all
+ ParsedAttributes Attributes(AttrFactory);
+ DeclSpec DS(AttrFactory);
+ Declarator ExDecl(DS, Attributes, DeclaratorContext::BlockLiteral);
+ ParseDeclarator(ExDecl);
+ ExceptionDecl =
+ Actions.ActOnExceptionDeclarator(getCurScope(), ExDecl, true);
}
T.consumeClose();
if (T.getCloseLocation().isInvalid())
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 93ee1b2e089..31d4355731b 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -16994,7 +16994,7 @@ Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D, bool isCatchAll) {
D.getIdentifierLoc());
Invalid = true;
}
- if (isCatchAll)
+ if (isCatchAll)
TInfo = Context.getTrivialTypeSourceInfo(Context.UnknownAnyTy,
D.getIdentifierLoc());
|
Using an extra bit for that in |
Hi @cor3ntin to review the updated fix, will format it later |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 that we should reduce the impact of the patch as much as possible.
Also every time we change the data member of decls and stmts, we need to update the serialization part.
LLVM_PREFERRED_TYPE(bool) | ||
unsigned EllipsisVar : 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we move this to ParmVarDeclBitfields
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might impact on the testcases failure , but I will check otherwise it will remain this
@@ -1053,6 +1053,10 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> { | |||
LLVM_PREFERRED_TYPE(bool) | |||
unsigned ExceptionVar : 1; | |||
|
|||
/// To Check the ellipsis |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment is not clear
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do it , its expected
/// Determine the Ellipsis (...) or not | ||
bool isEllipsisVariable() const { | ||
return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.EllipsisVar; | ||
} | ||
void setEllipsisVariable(bool EV) { | ||
assert(!isa<ParmVarDecl>(this)); | ||
NonParmVarDeclBits.EllipsisVar = EV; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we move this to ParmVarDecl?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might impact on the testcases failure , but I will check otherwise it will remain this
if (const VarDecl *ND = dyn_cast<VarDecl>(D)) | ||
if (ND->isEllipsisVariable()) | ||
JOS.attribute("catch_all", true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Format this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do it
if (const VarDecl *ND = dyn_cast<VarDecl>(D)) | ||
if (ND->isEllipsisVariable()) | ||
OS << " catch_all"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do it
@@ -16983,7 +16983,7 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, | |||
|
|||
/// ActOnExceptionDeclarator - Parsed the exception-declarator in a C++ catch | |||
/// handler. | |||
Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) { | |||
Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D, bool isCatchAll) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am hesitate on this. IIUC, previously the catch(...)
format is reprensented as the exception decl as nullptr? Then if yes, we should be able to reuse that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it won't be possible since if you see the ActOnExceptionDeclarator , we are not passing the Decl*, later we are updating the Decl*
else { | ||
CatchLoc = ConsumeToken(); | ||
// explicitly creating a var of type no-type for '...' and marking it as catch_all | ||
ParsedAttributes Attributes(AttrFactory); | ||
DeclSpec DS(AttrFactory); | ||
Declarator ExDecl(DS, Attributes, DeclaratorContext::BlockLiteral); | ||
ParseDeclarator(ExDecl); | ||
ExceptionDecl = Actions.ActOnExceptionDeclarator(getCurScope(), ExDecl, true); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am hesitate on this. IIUC, previously the catch(...) format is reprensented as the exception decl as nullptr? Then if yes, we should be able to reuse that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @ChuanqiXu9 , Thanks for the review!
I think it won't be possible since if you see the ActOnExceptionDeclarator , we are not passing the Decl*, later we are updating the Decl*
@@ -41,7 +41,7 @@ void TestCatch2() { | |||
try { | |||
} | |||
// CHECK-NEXT: CXXCatchStmt | |||
// CHECK-NEXT: NULL | |||
// CHECK-NEXT: VarDecl {{.*}} '<unknown type>' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can improve to print this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't do much here , its intently being created the var of unknown type
Please address this question first. Thanks! |
Hi @cor3ntin , |
I'd like more information on what was tried and why it didn't work. It would be better for us to associate the data with catch statements specifically because there's a lot fewer of those than there are variable declarations in general. |
Hi @AaronBallman I mean storing the ellipsis's location in catch stmt is not going to work, we need to add certain flags/function in VarDecl. Can you please review which I have raised currently one more time? |
I was suggesting that we should not walk a null node in that case (so modify the various AST walkers to check for a null pointer in that case and not walk down it), and instead we should have You're approaching this from a different angle, where we have a non-null CC @erichkeane for additional opinions. |
I VERY much don't think the extra decl is worth the effort. The Ellipsis Location should just be stored on the |
Output of the fixed 1st issue (catch(...))