Skip to content

Commit b4b0131

Browse files
committed
Avoid FieldDecl visitor
We can visit CXXDefaultInitExprs to find construction through [[unsafe_buffer_usage]] constructors of field initializers.
1 parent f18b946 commit b4b0131

File tree

4 files changed

+20
-46
lines changed

4 files changed

+20
-46
lines changed

clang/lib/Analysis/UnsafeBufferUsage.cpp

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,12 @@ class MatchDescendantVisitor
171171
return VisitorBase::TraverseCXXTypeidExpr(Node);
172172
}
173173

174+
bool TraverseCXXDefaultInitExpr(CXXDefaultInitExpr *Node) {
175+
if (!TraverseStmt(Node->getExpr()))
176+
return false;
177+
return VisitorBase::TraverseCXXDefaultInitExpr(Node);
178+
}
179+
174180
bool TraverseStmt(Stmt *Node, DataRecursionQueue *Queue = nullptr) {
175181
if (!Node)
176182
return true;
@@ -3927,16 +3933,6 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
39273933
Stmts.push_back(CI->getInit());
39283934
}
39293935
}
3930-
} else if (const auto *FlD = dyn_cast<FieldDecl>(D)) {
3931-
// Visit in-class initializers for fields.
3932-
if (!FlD->hasInClassInitializer())
3933-
return;
3934-
Stmts.push_back(FlD->getInClassInitializer());
3935-
// In a FieldDecl there is no function body, there is only a single
3936-
// statement, and the suggestions machinery is not set up to handle that
3937-
// kind of structure yet and would give poor suggestions or likely even hit
3938-
// asserts.
3939-
EmitSuggestions = false;
39403936
} else if (isa<BlockDecl>(D) || isa<ObjCMethodDecl>(D)) {
39413937
Stmts.push_back(D->getBody());
39423938
}

clang/lib/Sema/AnalysisBasedWarnings.cpp

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2510,38 +2510,6 @@ class CallableVisitor : public RecursiveASTVisitor<CallableVisitor> {
25102510
CallableVisitor(llvm::function_ref<void(const Decl *)> Callback)
25112511
: Callback(Callback) {}
25122512

2513-
bool VisitFieldDecl(FieldDecl *Node) {
2514-
DeclContext *DeclCtx;
2515-
if (auto *ID = dyn_cast<ObjCIvarDecl>(Node)) {
2516-
DeclCtx = cast<DeclContext>(ID->getContainingInterface());
2517-
} else {
2518-
RecordDecl *RD = Node->getParent();
2519-
if (auto *CCRD = dyn_cast<CXXRecordDecl>(RD);
2520-
CCRD && CCRD->isAggregate()) {
2521-
// Aggregates have implicitly generated constructors which are not
2522-
// traversed by our AST visitors at this time. The field initializers in
2523-
// an aggregate may never be used if the callers always explicitly
2524-
// initialize them, in which case we do not need to warn on unsafe
2525-
// buffer usage in the initializer.
2526-
//
2527-
// FIXME: We should go through the implicit aggregate initialization
2528-
// (either an implicit CXXConstructExpr for value-init or an implicit
2529-
// ListInitExpr for aggregate-init) to determine if a field's default
2530-
// initializer (CXXDefaultInitExpr) is actually used. If it is, then we
2531-
// should visit it, while retaining a reference to the caller for
2532-
// showing the path to the use of the default initializer in the
2533-
// warning.
2534-
return true;
2535-
}
2536-
DeclCtx = cast<DeclContext>(RD);
2537-
}
2538-
if (DeclCtx->isDependentContext())
2539-
return true; // Not to analyze dependent decl
2540-
if (Node->hasInClassInitializer())
2541-
Callback(Node);
2542-
return true;
2543-
}
2544-
25452513
bool VisitFunctionDecl(FunctionDecl *Node) {
25462514
if (cast<DeclContext>(Node)->isDependentContext())
25472515
return true; // Not to analyze dependent decl

clang/test/SemaCXX/warn-unsafe-buffer-usage-function-attr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ struct HoldsUnsafeMembers {
128128

129129
UnsafeMembers FromCtor;
130130
UnsafeMembers FromCtor2;
131-
UnsafeMembers FromField{3}; // expected-warning{{function introduces unsafe buffer manipulation}}
131+
UnsafeMembers FromField{3}; // expected-warning 2{{function introduces unsafe buffer manipulation}}
132132
};
133133

134134
struct SubclassUnsafeMembers : public UnsafeMembers {

clang/test/SemaCXX/warn-unsafe-buffer-usage-in-container-span-construct.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,12 +158,22 @@ namespace test_flag {
158158
}
159159
} //namespace test_flag
160160

161-
struct HoldsStdSpan {
161+
struct HoldsStdSpanAndInitializedInCtor {
162162
char* Ptr;
163163
unsigned Size;
164-
std::span<char> Span{Ptr, Size}; // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}
164+
std::span<char> Span{Ptr, Size}; // no-warning (this code is unreachable)
165165

166-
HoldsStdSpan(char* P, unsigned S)
166+
HoldsStdSpanAndInitializedInCtor(char* P, unsigned S)
167167
: Span(P, S) // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}
168168
{}
169169
};
170+
171+
struct HoldsStdSpanAndNotInitializedInCtor {
172+
char* Ptr;
173+
unsigned Size;
174+
std::span<char> Span{Ptr, Size}; // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}
175+
176+
HoldsStdSpanAndNotInitializedInCtor(char* P, unsigned S)
177+
: Ptr(P), Size(S)
178+
{}
179+
};

0 commit comments

Comments
 (0)