Skip to content

Commit 5696c42

Browse files
committed
Merge branch 'main' of https://github.com/llvm/llvm-project into private_is_an_evil_default
2 parents 7fcb506 + fc36252 commit 5696c42

File tree

263 files changed

+10964
-3664
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

263 files changed

+10964
-3664
lines changed

clang-tools-extra/clang-tidy/ClangTidy.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,6 @@ ClangTidyASTConsumerFactory::createASTConsumer(
458458
if (!AnalyzerOptions.CheckersAndPackages.empty()) {
459459
setStaticAnalyzerCheckerOpts(Context.getOptions(), AnalyzerOptions);
460460
AnalyzerOptions.AnalysisDiagOpt = PD_NONE;
461-
AnalyzerOptions.eagerlyAssumeBinOpBifurcation = true;
462461
std::unique_ptr<ento::AnalysisASTConsumer> AnalysisConsumer =
463462
ento::CreateAnalysisConsumer(Compiler);
464463
AnalysisConsumer->AddDiagnosticConsumer(

clang/docs/ReleaseNotes.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,19 @@ C++ Specific Potentially Breaking Changes
9999
// Was error, now evaluates to false.
100100
constexpr bool b = f() == g();
101101
102+
- Clang will now correctly not consider pointers to non classes for covariance.
103+
104+
.. code-block:: c++
105+
106+
struct A {
107+
virtual const int *f() const;
108+
};
109+
struct B : A {
110+
// Return type has less cv-qualification but doesn't point to a class.
111+
// Error will be generated.
112+
int *f() const override;
113+
};
114+
102115
- The warning ``-Wdeprecated-literal-operator`` is now on by default, as this is
103116
something that WG21 has shown interest in removing from the language. The
104117
result is that anyone who is compiling with ``-Werror`` should see this

clang/include/clang/AST/DeclTemplate.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2085,7 +2085,11 @@ class ClassTemplateSpecializationDecl : public CXXRecordDecl,
20852085
class ClassTemplatePartialSpecializationDecl
20862086
: public ClassTemplateSpecializationDecl {
20872087
/// The list of template parameters
2088-
TemplateParameterList* TemplateParams = nullptr;
2088+
TemplateParameterList *TemplateParams = nullptr;
2089+
2090+
/// The set of "injected" template arguments used within this
2091+
/// partial specialization.
2092+
TemplateArgument *InjectedArgs = nullptr;
20892093

20902094
/// The class template partial specialization from which this
20912095
/// class template partial specialization was instantiated.
@@ -2132,6 +2136,10 @@ class ClassTemplatePartialSpecializationDecl
21322136
return TemplateParams;
21332137
}
21342138

2139+
/// Retrieve the template arguments list of the template parameter list
2140+
/// of this template.
2141+
ArrayRef<TemplateArgument> getInjectedTemplateArgs();
2142+
21352143
/// \brief All associated constraints of this partial specialization,
21362144
/// including the requires clause and any constraints derived from
21372145
/// constrained-parameters.
@@ -2856,6 +2864,10 @@ class VarTemplatePartialSpecializationDecl
28562864
/// The list of template parameters
28572865
TemplateParameterList *TemplateParams = nullptr;
28582866

2867+
/// The set of "injected" template arguments used within this
2868+
/// partial specialization.
2869+
TemplateArgument *InjectedArgs = nullptr;
2870+
28592871
/// The variable template partial specialization from which this
28602872
/// variable template partial specialization was instantiated.
28612873
///
@@ -2902,6 +2914,10 @@ class VarTemplatePartialSpecializationDecl
29022914
return TemplateParams;
29032915
}
29042916

2917+
/// Retrieve the template arguments list of the template parameter list
2918+
/// of this template.
2919+
ArrayRef<TemplateArgument> getInjectedTemplateArgs();
2920+
29052921
/// \brief All associated constraints of this partial specialization,
29062922
/// including the requires clause and any constraints derived from
29072923
/// constrained-parameters.
Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
//===-- CachedConstAccessorsLattice.h ---------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file defines the lattice mixin that additionally maintains a cache of
10+
// stable method call return values to model const accessor member functions.
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_CACHED_CONST_ACCESSORS_LATTICE_H
14+
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_CACHED_CONST_ACCESSORS_LATTICE_H
15+
16+
#include "clang/AST/Expr.h"
17+
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
18+
#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
19+
#include "clang/Analysis/FlowSensitive/StorageLocation.h"
20+
#include "clang/Analysis/FlowSensitive/Value.h"
21+
#include "llvm/ADT/DenseMap.h"
22+
#include "llvm/ADT/STLFunctionalExtras.h"
23+
24+
namespace clang {
25+
namespace dataflow {
26+
27+
/// A mixin for a lattice that additionally maintains a cache of stable method
28+
/// call return values to model const accessors methods. When a non-const method
29+
/// is called, the cache should be cleared causing the next call to a const
30+
/// method to be considered a different value. NOTE: The user is responsible for
31+
/// clearing the cache.
32+
///
33+
/// For example:
34+
///
35+
/// class Bar {
36+
/// public:
37+
/// const std::optional<Foo>& getFoo() const;
38+
/// void clear();
39+
/// };
40+
//
41+
/// void func(Bar& s) {
42+
/// if (s.getFoo().has_value()) {
43+
/// use(s.getFoo().value()); // safe (checked earlier getFoo())
44+
/// s.clear();
45+
/// use(s.getFoo().value()); // unsafe (invalidate cache for s)
46+
/// }
47+
/// }
48+
template <typename Base> class CachedConstAccessorsLattice : public Base {
49+
public:
50+
using Base::Base; // inherit all constructors
51+
52+
/// Creates or returns a previously created `Value` associated with a const
53+
/// method call `obj.getFoo()` where `RecordLoc` is the
54+
/// `RecordStorageLocation` of `obj`.
55+
/// Returns nullptr if unable to find or create a value.
56+
///
57+
/// Requirements:
58+
///
59+
/// - `CE` should return a value (not a reference or record type)
60+
Value *
61+
getOrCreateConstMethodReturnValue(const RecordStorageLocation &RecordLoc,
62+
const CallExpr *CE, Environment &Env);
63+
64+
/// Creates or returns a previously created `StorageLocation` associated with
65+
/// a const method call `obj.getFoo()` where `RecordLoc` is the
66+
/// `RecordStorageLocation` of `obj`.
67+
///
68+
/// The callback `Initialize` runs on the storage location if newly created.
69+
/// Returns nullptr if unable to find or create a value.
70+
///
71+
/// Requirements:
72+
///
73+
/// - `CE` should return a location (GLValue or a record type).
74+
StorageLocation *getOrCreateConstMethodReturnStorageLocation(
75+
const RecordStorageLocation &RecordLoc, const CallExpr *CE,
76+
Environment &Env, llvm::function_ref<void(StorageLocation &)> Initialize);
77+
78+
void clearConstMethodReturnValues(const RecordStorageLocation &RecordLoc) {
79+
ConstMethodReturnValues.erase(&RecordLoc);
80+
}
81+
82+
void clearConstMethodReturnStorageLocations(
83+
const RecordStorageLocation &RecordLoc) {
84+
ConstMethodReturnStorageLocations.erase(&RecordLoc);
85+
}
86+
87+
bool operator==(const CachedConstAccessorsLattice &Other) const {
88+
return Base::operator==(Other);
89+
}
90+
91+
LatticeJoinEffect join(const CachedConstAccessorsLattice &Other);
92+
93+
private:
94+
// Maps a record storage location and const method to the value to return
95+
// from that const method.
96+
using ConstMethodReturnValuesType =
97+
llvm::SmallDenseMap<const RecordStorageLocation *,
98+
llvm::SmallDenseMap<const FunctionDecl *, Value *>>;
99+
ConstMethodReturnValuesType ConstMethodReturnValues;
100+
101+
// Maps a record storage location and const method to the record storage
102+
// location to return from that const method.
103+
using ConstMethodReturnStorageLocationsType = llvm::SmallDenseMap<
104+
const RecordStorageLocation *,
105+
llvm::SmallDenseMap<const FunctionDecl *, StorageLocation *>>;
106+
ConstMethodReturnStorageLocationsType ConstMethodReturnStorageLocations;
107+
};
108+
109+
namespace internal {
110+
111+
template <typename T>
112+
llvm::SmallDenseMap<const RecordStorageLocation *,
113+
llvm::SmallDenseMap<const FunctionDecl *, T *>>
114+
joinConstMethodMap(
115+
const llvm::SmallDenseMap<const RecordStorageLocation *,
116+
llvm::SmallDenseMap<const FunctionDecl *, T *>>
117+
&Map1,
118+
const llvm::SmallDenseMap<const RecordStorageLocation *,
119+
llvm::SmallDenseMap<const FunctionDecl *, T *>>
120+
&Map2,
121+
LatticeEffect &Effect) {
122+
llvm::SmallDenseMap<const RecordStorageLocation *,
123+
llvm::SmallDenseMap<const FunctionDecl *, T *>>
124+
Result;
125+
for (auto &[Loc, DeclToT] : Map1) {
126+
auto It = Map2.find(Loc);
127+
if (It == Map2.end()) {
128+
Effect = LatticeJoinEffect::Changed;
129+
continue;
130+
}
131+
const auto &OtherDeclToT = It->second;
132+
auto &JoinedDeclToT = Result[Loc];
133+
for (auto [Func, Var] : DeclToT) {
134+
T *OtherVar = OtherDeclToT.lookup(Func);
135+
if (OtherVar == nullptr || OtherVar != Var) {
136+
Effect = LatticeJoinEffect::Changed;
137+
continue;
138+
}
139+
JoinedDeclToT.insert({Func, Var});
140+
}
141+
}
142+
return Result;
143+
}
144+
145+
} // namespace internal
146+
147+
template <typename Base>
148+
LatticeEffect CachedConstAccessorsLattice<Base>::join(
149+
const CachedConstAccessorsLattice<Base> &Other) {
150+
151+
LatticeEffect Effect = Base::join(Other);
152+
153+
// For simplicity, we only retain values that are identical, but not ones that
154+
// are non-identical but equivalent. This is likely to be sufficient in
155+
// practice, and it reduces implementation complexity considerably.
156+
157+
ConstMethodReturnValues = internal::joinConstMethodMap<Value>(
158+
ConstMethodReturnValues, Other.ConstMethodReturnValues, Effect);
159+
160+
ConstMethodReturnStorageLocations =
161+
internal::joinConstMethodMap<StorageLocation>(
162+
ConstMethodReturnStorageLocations,
163+
Other.ConstMethodReturnStorageLocations, Effect);
164+
165+
return Effect;
166+
}
167+
168+
template <typename Base>
169+
Value *CachedConstAccessorsLattice<Base>::getOrCreateConstMethodReturnValue(
170+
const RecordStorageLocation &RecordLoc, const CallExpr *CE,
171+
Environment &Env) {
172+
QualType Type = CE->getType();
173+
assert(!Type.isNull());
174+
assert(!Type->isReferenceType());
175+
assert(!Type->isRecordType());
176+
177+
auto &ObjMap = ConstMethodReturnValues[&RecordLoc];
178+
const FunctionDecl *DirectCallee = CE->getDirectCallee();
179+
if (DirectCallee == nullptr)
180+
return nullptr;
181+
auto it = ObjMap.find(DirectCallee);
182+
if (it != ObjMap.end())
183+
return it->second;
184+
185+
Value *Val = Env.createValue(Type);
186+
if (Val != nullptr)
187+
ObjMap.insert({DirectCallee, Val});
188+
return Val;
189+
}
190+
191+
template <typename Base>
192+
StorageLocation *
193+
CachedConstAccessorsLattice<Base>::getOrCreateConstMethodReturnStorageLocation(
194+
const RecordStorageLocation &RecordLoc, const CallExpr *CE,
195+
Environment &Env, llvm::function_ref<void(StorageLocation &)> Initialize) {
196+
QualType Type = CE->getType();
197+
assert(!Type.isNull());
198+
assert(CE->isGLValue() || Type->isRecordType());
199+
auto &ObjMap = ConstMethodReturnStorageLocations[&RecordLoc];
200+
const FunctionDecl *DirectCallee = CE->getDirectCallee();
201+
if (DirectCallee == nullptr)
202+
return nullptr;
203+
auto it = ObjMap.find(DirectCallee);
204+
if (it != ObjMap.end())
205+
return it->second;
206+
207+
StorageLocation &Loc =
208+
Env.createStorageLocation(CE->getType().getNonReferenceType());
209+
Initialize(Loc);
210+
211+
ObjMap.insert({DirectCallee, &Loc});
212+
return &Loc;
213+
}
214+
215+
} // namespace dataflow
216+
} // namespace clang
217+
218+
#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_CACHED_CONST_ACCESSORS_LATTICE_H

clang/include/clang/CodeGen/CodeGenABITypes.h

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,25 @@ const CGFunctionInfo &arrangeCXXMethodType(CodeGenModule &CGM,
7575
const FunctionProtoType *FTP,
7676
const CXXMethodDecl *MD);
7777

78-
const CGFunctionInfo &arrangeFreeFunctionCall(CodeGenModule &CGM,
79-
CanQualType returnType,
80-
ArrayRef<CanQualType> argTypes,
81-
FunctionType::ExtInfo info,
82-
RequiredArgs args);
78+
const CGFunctionInfo &
79+
arrangeCXXMethodCall(CodeGenModule &CGM, CanQualType returnType,
80+
ArrayRef<CanQualType> argTypes, FunctionType::ExtInfo info,
81+
ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos,
82+
RequiredArgs args);
83+
84+
const CGFunctionInfo &arrangeFreeFunctionCall(
85+
CodeGenModule &CGM, CanQualType returnType, ArrayRef<CanQualType> argTypes,
86+
FunctionType::ExtInfo info,
87+
ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos,
88+
RequiredArgs args);
89+
90+
// An overload with an empty `paramInfos`
91+
inline const CGFunctionInfo &
92+
arrangeFreeFunctionCall(CodeGenModule &CGM, CanQualType returnType,
93+
ArrayRef<CanQualType> argTypes,
94+
FunctionType::ExtInfo info, RequiredArgs args) {
95+
return arrangeFreeFunctionCall(CGM, returnType, argTypes, info, {}, args);
96+
}
8397

8498
/// Returns the implicit arguments to add to a complete, non-delegating C++
8599
/// constructor call.

clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -299,13 +299,12 @@ ANALYZER_OPTION(
299299

300300
ANALYZER_OPTION(
301301
bool, ShouldEagerlyAssume, "eagerly-assume",
302-
"Whether we should eagerly assume evaluations of conditionals, thus, "
303-
"bifurcating the path. This indicates how the engine should handle "
304-
"expressions such as: 'x = (y != 0)'. When this is true then the "
305-
"subexpression 'y != 0' will be eagerly assumed to be true or false, thus "
306-
"evaluating it to the integers 0 or 1 respectively. The upside is that "
307-
"this can increase analysis precision until we have a better way to lazily "
308-
"evaluate such logic. The downside is that it eagerly bifurcates paths.",
302+
"If this is enabled (the default behavior), when the analyzer encounters "
303+
"a comparison operator or logical negation, it immediately splits the "
304+
"state to separate the case when the expression is true and the case when "
305+
"it's false. The upside is that this can increase analysis precision until "
306+
"we have a better way to lazily evaluate such logic; the downside is that "
307+
"it eagerly bifurcates paths.",
309308
true)
310309

311310
ANALYZER_OPTION(

clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,6 @@ class AnalyzerOptions : public RefCountedBase<AnalyzerOptions> {
229229
unsigned AnalyzerDisplayProgress : 1;
230230
unsigned AnalyzerNoteAnalysisEntryPoints : 1;
231231

232-
unsigned eagerlyAssumeBinOpBifurcation : 1;
233-
234232
unsigned TrimGraph : 1;
235233
unsigned visualizeExplodedGraphWithGraphViz : 1;
236234
unsigned UnoptimizedCFG : 1;
@@ -293,9 +291,9 @@ class AnalyzerOptions : public RefCountedBase<AnalyzerOptions> {
293291
ShowConfigOptionsList(false),
294292
ShouldEmitErrorsOnInvalidConfigValue(false), AnalyzeAll(false),
295293
AnalyzerDisplayProgress(false), AnalyzerNoteAnalysisEntryPoints(false),
296-
eagerlyAssumeBinOpBifurcation(false), TrimGraph(false),
297-
visualizeExplodedGraphWithGraphViz(false), UnoptimizedCFG(false),
298-
PrintStats(false), NoRetryExhausted(false), AnalyzerWerror(false) {}
294+
TrimGraph(false), visualizeExplodedGraphWithGraphViz(false),
295+
UnoptimizedCFG(false), PrintStats(false), NoRetryExhausted(false),
296+
AnalyzerWerror(false) {}
299297

300298
/// Interprets an option's string value as a boolean. The "true" string is
301299
/// interpreted as true and the "false" string is interpreted as false.

clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -583,14 +583,13 @@ class ExprEngine {
583583
ExplodedNode *Pred,
584584
ExplodedNodeSet &Dst);
585585

586-
/// evalEagerlyAssumeBinOpBifurcation - Given the nodes in 'Src', eagerly assume symbolic
587-
/// expressions of the form 'x != 0' and generate new nodes (stored in Dst)
588-
/// with those assumptions.
589-
void evalEagerlyAssumeBinOpBifurcation(ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
590-
const Expr *Ex);
586+
/// evalEagerlyAssumeBifurcation - Given the nodes in 'Src', eagerly assume
587+
/// concrete boolean values for 'Ex', storing the resulting nodes in 'Dst'.
588+
void evalEagerlyAssumeBifurcation(ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
589+
const Expr *Ex);
591590

592591
static std::pair<const ProgramPointTag *, const ProgramPointTag *>
593-
geteagerlyAssumeBinOpBifurcationTags();
592+
getEagerlyAssumeBifurcationTags();
594593

595594
ProgramStateRef handleLValueBitCast(ProgramStateRef state, const Expr *Ex,
596595
const LocationContext *LCtx, QualType T,

0 commit comments

Comments
 (0)