-
Notifications
You must be signed in to change notification settings - Fork 15.2k
Check if clang::FieldDecl has constant-integer bit width before getting the width #148692
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
Check if clang::FieldDecl has constant-integer bit width before getting the width #148692
Conversation
|
@llvm/pr-subscribers-clang Author: None (higher-performance) ChangesThis avoids crashing due to template-dependent bit widths, such as in the following: Full diff: https://github.com/llvm/llvm-project/pull/148692.diff 3 Files Affected:
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index f70a039bf3517..f88c206ca4d44 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -3234,6 +3234,11 @@ class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> {
return hasInClassInitializer() ? InitAndBitWidth->BitWidth : BitWidth;
}
+ /// Determines whether the bit width of this field is a constant integer.
+ /// This may not always be the case, such as inside template-dependent
+ /// expressions.
+ bool hasConstantIntegerBitWidth() const;
+
/// Computes the bit width of this field, if this is a bit field.
/// May not be called on non-bitfields.
/// Note that in order to successfully use this function, the bitwidth
diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h
index bae004896c11f..fcce9b5c38b23 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -709,7 +709,8 @@ AST_MATCHER(FieldDecl, isBitField) {
/// fieldDecl(hasBitWidth(2))
/// matches 'int a;' and 'int c;' but not 'int b;'.
AST_MATCHER_P(FieldDecl, hasBitWidth, unsigned, Width) {
- return Node.isBitField() && Node.getBitWidthValue() == Width;
+ return Node.isBitField() && Node.hasConstantIntegerBitWidth() &&
+ Node.getBitWidthValue() == Width;
}
/// Matches non-static data members that have an in-class initializer.
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 8855d0107daca..f4cb5a026e25f 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -4677,11 +4677,14 @@ void FieldDecl::setLazyInClassInitializer(LazyDeclStmtPtr NewInit) {
Init = NewInit;
}
+bool FieldDecl::hasConstantIntegerBitWidth() const {
+ const auto *CE = dyn_cast_if_present<ConstantExpr>(getBitWidth());
+ return CE && CE->getAPValueResult().isInt();
+}
+
unsigned FieldDecl::getBitWidthValue() const {
assert(isBitField() && "not a bitfield");
- assert(isa<ConstantExpr>(getBitWidth()));
- assert(cast<ConstantExpr>(getBitWidth())->hasAPValueResult());
- assert(cast<ConstantExpr>(getBitWidth())->getAPValueResult().isInt());
+ assert(hasConstantIntegerBitWidth());
return cast<ConstantExpr>(getBitWidth())
->getAPValueResult()
.getInt()
|
|
Can you add tests (and a release note) Thanks! |
…ng the width, to avoid crashing inside templates
715aacb to
668c02d
Compare
|
Done. |
| /// matches 'int a;' and 'int c;' but not 'int b;'. | ||
| AST_MATCHER_P(FieldDecl, hasBitWidth, unsigned, Width) { | ||
| return Node.isBitField() && Node.getBitWidthValue() == Width; | ||
| return Node.isBitField() && Node.hasConstantIntegerBitWidth() && |
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 looks like you are only testing the Node.hasConstantIntegerBitWidth() == true case in the test below. If that is correct we should add a test that covers both cases and any other combinations of these conditions not covered by testing.
This avoids crashing due to template-dependent bit widths, such as in the following: