Skip to content

Commit 2531895

Browse files
committed
Merge remote-tracking branch 'upstream/master'
2 parents cfc998e + 3caa72a commit 2531895

37 files changed

+3673
-416
lines changed

clang/include/clang/AST/ASTContext.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2372,6 +2372,25 @@ class ASTContext : public RefCountedBase<ASTContext> {
23722372
getCanonicalType(T2).getTypePtr();
23732373
}
23742374

2375+
/// Determine whether the given types are equivalent after
2376+
/// cvr-qualifiers have been removed, ignoring any difference
2377+
/// in pointer checkedness.
2378+
bool hasSameUnqualifiedUncheckedType(QualType T1, QualType T2) const {
2379+
if (hasSameUnqualifiedType(T1, T2))
2380+
return true;
2381+
2382+
// See if the only difference between T1 and T2 is that one is a
2383+
// checked pointer type and one is an unchecked pointer type.
2384+
if (T1->isPointerType() && T2->isPointerType()) {
2385+
const PointerType *PtrType1 = T1->getAs<PointerType>();
2386+
const PointerType *PtrType2 = T2->getAs<PointerType>();
2387+
return hasSameUnqualifiedUncheckedType(PtrType1->getPointeeType(),
2388+
PtrType2->getPointeeType());
2389+
}
2390+
2391+
return false;
2392+
}
2393+
23752394
bool hasSameNullabilityTypeQualifier(QualType SubT, QualType SuperT,
23762395
bool IsParam) const {
23772396
auto SubTnullability = SubT->getNullability(*this);

clang/include/clang/AST/CanonBounds.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@ namespace clang {
118118
/// \brief Lexicographic comparison of expressions that can occur in
119119
/// bounds expressions.
120120
Result CompareExpr(const Expr *E1, const Expr *E2);
121+
/// \brief Semantic comparison of expressions that can occur in
122+
/// bounds expressions. A return value of true indicates that the two
123+
/// expressions are equivalent semantically.
124+
bool CompareExprSemantically(const Expr *E1, const Expr *E2);
121125

122126
/// \brief Compare declarations that may be used by expressions or
123127
/// or types.

clang/include/clang/AST/Decl.h

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -708,9 +708,10 @@ class DeclaratorDecl : public ValueDecl {
708708
DeclarationName N, QualType T, TypeSourceInfo *TInfo,
709709
SourceLocation StartL)
710710
: ValueDecl(DK, DC, L, N, T), DeclInfo(TInfo), InnerLocStart(StartL),
711-
Annotations(nullptr) {}
711+
Annotations(nullptr), NormalizedBounds(nullptr) {}
712712

713713
BoundsAnnotations *Annotations;
714+
BoundsExpr *NormalizedBounds;
714715
public:
715716
friend class ASTDeclReader;
716717
friend class ASTDeclWriter;
@@ -819,6 +820,30 @@ class DeclaratorDecl : public ValueDecl {
819820
Annotations->setBoundsExpr(E);
820821
}
821822

823+
// \brief The bounds expression for this declaration, expanded to a
824+
// range bounds expression.
825+
BoundsExpr *getNormalizedBounds() const {
826+
return const_cast<DeclaratorDecl *>(this)->getNormalizedBounds();
827+
}
828+
829+
// \brief The bounds expression for this declaration, expanded to a
830+
// range bounds expression.
831+
BoundsExpr *getNormalizedBounds() {
832+
return NormalizedBounds;
833+
}
834+
835+
// \brief Set the bounds expression for this declaration, expanded to a
836+
// range bounds expression.
837+
void setNormalizedBounds(BoundsExpr *E) const {
838+
const_cast<DeclaratorDecl *>(this)->setNormalizedBounds(E);
839+
}
840+
841+
// \brief Set the bounds expression for this declaration, expanded to a
842+
// range bounds expression.
843+
void setNormalizedBounds(BoundsExpr *E) {
844+
NormalizedBounds = E;
845+
}
846+
822847
/// \brief The Checked C interop type declared or inferred for this
823848
/// declaration. For function declarations, this is the return
824849
/// interop type of the function. Null if none has been declared

clang/include/clang/AST/PreorderAST.h

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
//===------- PreorderAST.h: An n-ary preorder abstract syntax tree -------===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
6+
// See https://llvm.org/LICENSE.txt for license information.
7+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8+
//
9+
//===----------------------------------------------------------------------===//
10+
//
11+
// This file defines the interface for an n-ary preorder abstract syntax tree
12+
// which is used to semantically compare two expressions.
13+
//
14+
//===----------------------------------------------------------------------===//
15+
16+
#ifndef LLVM_CLANG_PREORDER_AST_H
17+
#define LLVM_CLANG_PREORDER_AST_H
18+
19+
#include "clang/AST/ASTContext.h"
20+
#include "clang/AST/CanonBounds.h"
21+
#include "clang/AST/Expr.h"
22+
23+
namespace clang {
24+
25+
using Result = Lexicographic::Result;
26+
27+
// Each binary operator of an expression results in a new node of the
28+
// PreorderAST. Each node contains 3 fields:
29+
// Opc: The opcode of the operator.
30+
// Vars: A list of variables in the sub expression.
31+
// Const: Constants of the sub expression are folded.
32+
33+
struct Node {
34+
BinaryOperator::Opcode Opc;
35+
std::vector<const VarDecl *> Vars;
36+
llvm::APSInt Const;
37+
// HasConst indicates whether there is a constant in the node. This is used
38+
// to differentiate between an absence of a constant and a constant of value
39+
// 0.
40+
bool HasConst;
41+
Node *Parent, *Left, *Right;
42+
43+
Node(Node *Parent) :
44+
Opc(BO_Add), HasConst(false),
45+
Parent(Parent), Left(nullptr), Right(nullptr) {}
46+
47+
// Is the operator commutative and associative?
48+
bool IsOpCommutativeAndAssociative() {
49+
return Opc == BO_Add || Opc == BO_Mul;
50+
}
51+
};
52+
53+
class PreorderAST {
54+
private:
55+
ASTContext &Ctx;
56+
Lexicographic Lex;
57+
llvm::raw_ostream &OS;
58+
bool Error;
59+
Node *Root;
60+
61+
// Create a PreorderAST for the expression E.
62+
// @param[in] E is the sub expression which needs to be added to N.
63+
// @param[in] N is the current node of the AST.
64+
// @param[in] Parent is the parent node for N.
65+
void Create(Expr *E, Node *N = nullptr, Node *Parent = nullptr);
66+
67+
// Sort the variables in a node of the AST.
68+
// @param[in] N is current node of the AST.
69+
void Sort(Node *N);
70+
71+
// Check if the two AST nodes N1 and N2 are equal.
72+
// @param[in] N1 is the first node.
73+
// @param[in] N2 is the second node.
74+
// @return Returns a boolean indicating whether N1 and N2 are equal.
75+
bool IsEqual(Node *N1, Node *N2);
76+
77+
// Set Error in case an error occurs during transformation of the AST.
78+
void SetError() { Error = true; }
79+
80+
// Print the PreorderAST.
81+
// @param[in] N is the current node of the AST.
82+
void PrettyPrint(Node *N);
83+
84+
// Cleanup the memory consumed by node N.
85+
// @param[in] N is the current node of the AST.
86+
void Cleanup(Node *N);
87+
88+
// A DeclRefExpr can be a reference either to an array subscript (in which
89+
// case it is wrapped around a ArrayToPointerDecay cast) or to a pointer
90+
// dereference (in which case it is wrapped around an LValueToRValue cast).
91+
// @param[in] An expression E.
92+
// @return Returns a DeclRefExpr if E is a DeclRefExpr, otherwise nullptr.
93+
DeclRefExpr *GetDeclOperand(Expr *E);
94+
95+
public:
96+
PreorderAST(ASTContext &Ctx, Expr *E) :
97+
Ctx(Ctx), Lex(Lexicographic(Ctx, nullptr)), OS(llvm::outs()),
98+
Error(false), Root(nullptr) {
99+
Create(E);
100+
}
101+
102+
// Normalize the input expression through a series of transforms on the
103+
// preorder AST. The Error field is set if an error is encountered during
104+
// transformation of the AST.
105+
void Normalize();
106+
107+
// Check if the two ASTs are equal. This is intended to be called from
108+
// outside this class and invokes IsEqual on the root nodes of the two ASTs
109+
// to recursively compare the AST nodes.
110+
// @param[in] this is the first AST.
111+
// @param[in] P is the second AST.
112+
// @return Returns a bool indicating whether the two ASTs are equal.
113+
bool IsEqual(PreorderAST &P) { return IsEqual(Root, P.Root); }
114+
115+
// Check if an error has occurred during transformation of the AST. This
116+
// is intended to be called from outside this class to check if an error
117+
// has occurred during comparison of expressions.
118+
// @return Whether an error has occurred or not.
119+
bool GetError() { return Error; }
120+
121+
// Cleanup the memory consumed by the AST. This is intended to be called
122+
// from outside this class and invokes Cleanup on the root node which
123+
// recursively deletes the AST.
124+
void Cleanup() { Cleanup(Root); }
125+
};
126+
127+
} // end namespace clang
128+
#endif

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10164,17 +10164,20 @@ def err_bounds_type_annotation_lost_checking : Error<
1016410164

1016510165
def warn_bounds_declaration_invalid : Warning<
1016610166
"cannot prove declared bounds for %1 are valid after "
10167-
"%select{assignment|initialization}0">,
10167+
"%select{assignment|initialization|statement}0">,
1016810168
InGroup<CheckBoundsDeclsUnchecked>;
1016910169

1017010170
def warn_checked_scope_bounds_declaration_invalid : Warning<
1017110171
"cannot prove declared bounds for %1 are valid after "
10172-
"%select{assignment|initialization}0">,
10172+
"%select{assignment|initialization|statement}0">,
1017310173
InGroup<CheckBoundsDeclsChecked>;
1017410174

1017510175
def error_bounds_declaration_invalid : Error<
1017610176
"declared bounds for %1 are invalid after "
10177-
"%select{assignment|initialization}0">;
10177+
"%select{assignment|initialization|statement}0">;
10178+
10179+
def err_unknown_inferred_bounds : Error<
10180+
"inferred bounds for %0 are unknown after statement">;
1017810181

1017910182
def note_declared_bounds : Note<
1018010183
"(expanded) declared bounds are '%0'">;
@@ -10188,6 +10191,13 @@ def err_bounds_type_annotation_lost_checking : Error<
1018810191
def note_required_bounds : Note<
1018910192
"(expanded) required bounds are '%0'">;
1019010193

10194+
def note_lost_variable : Note<
10195+
"lost the value of the variable '%0' "
10196+
"which is used in the (expanded) inferred bounds '%1' of %2">;
10197+
10198+
def note_unknown_source_bounds : Note<
10199+
"assigned expression '%0' with unknown bounds to %1">;
10200+
1019110201
def err_modifying_expr_not_supported : Error<
1019210202
"argument must be a non-modifying expression because %ordinal0 parameter "
1019310203
"is used in a bounds expression">;

clang/include/clang/Basic/LangOptions.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ LANGOPT(CPlusPlus17 , 1, 0, "C++17")
9494
LANGOPT(CPlusPlus2a , 1, 0, "C++2a")
9595
LANGOPT(ObjC , 1, 0, "Objective-C")
9696
LANGOPT(CheckedC , 1, 0, "Checked C extension")
97+
LANGOPT(CheckedCConverter , 1, 0, "Automated Checked C converter mode")
9798
BENIGN_LANGOPT(ObjCDefaultSynthProperties , 1, 0,
9899
"Objective-C auto-synthesized properties")
99100
BENIGN_LANGOPT(EncodeExtendedBlockSig , 1, 0,

clang/include/clang/Driver/Options.td

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -800,7 +800,9 @@ def fbuiltin_module_map : Flag <["-"], "fbuiltin-module-map">, Group<f_Group>,
800800
def fcheckedc_extension : Flag<["-"], "fcheckedc-extension">, Group<f_Group>, Flags<[CC1Option]>,
801801
HelpText<"Accept Checked C extension">;
802802
def fno_checkedc_extension : Flag<["-"], "fno-checkedc-extension">, Group<f_Group>, Flags<[CC1Option]>,
803-
HelpText<"Do ont accept Checked C extension">;
803+
HelpText<"Do not accept Checked C extension">;
804+
def fcheckedc_convert_tool : Flag<["-"], "fcheckedc-convert-tool">, Group<f_Group>, Flags<[CC1Option]>,
805+
HelpText<"Enable Checked C converter tool mode (supposed to be run by tools that needs only AST)">;
804806
def fdump_extracted_comparison_facts : Flag<["-"], "fdump-extracted-comparison-facts">, Group<f_Group>, Flags<[CC1Option]>,
805807
HelpText<"Dump extracted comparison facts">;
806808
def fdump_widened_bounds : Flag<["-"], "fdump-widened-bounds">, Group<f_Group>, Flags<[CC1Option]>,

clang/include/clang/Sema/BoundsAnalysis.h

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ namespace clang {
9696
// 2. any variable used in the bounds expr of V is assigned to in S.
9797
using StmtDeclSetTy = llvm::DenseMap<const Stmt *, DeclSetTy>;
9898

99+
// StmtSet denotes a set of Stmts.
100+
using StmtSet = llvm::SmallPtrSet<const Stmt *, 16>;
101+
99102
class BoundsAnalysis {
100103
private:
101104
Sema &S;
@@ -184,7 +187,9 @@ namespace clang {
184187

185188
// Run the dataflow analysis to widen bounds for ntptr's.
186189
// @param[in] FD is the current function.
187-
void WidenBounds(FunctionDecl *FD);
190+
// @param[in] NestedStmts is a set of top-level statements that are
191+
// nested in another top-level statement.
192+
void WidenBounds(FunctionDecl *FD, StmtSet NestedStmts);
188193

189194
// Get the widened bounds for block B.
190195
// @param[in] B is the block for which the widened bounds are needed.
@@ -214,7 +219,9 @@ namespace clang {
214219
// Compute Kill set for each block in BlockMap. For a block B, if a
215220
// variable V is assigned to in B by Stmt S, then the pair S:V is added to
216221
// the Kill set for the block.
217-
void ComputeKillSets();
222+
// @param[in] NestedStmts is a set of top-level statements that are
223+
// nested in another top-level statement.
224+
void ComputeKillSets(StmtSet NestedStmts);
218225

219226
// Compute In set for each block in BlockMap. In[B1] = n Out[B*->B1], where
220227
// B* are all preds of B1.
@@ -314,10 +321,12 @@ namespace clang {
314321
// @param[in] FD is the current function.
315322
void CollectNtPtrsInScope(FunctionDecl *FD);
316323

317-
// If variable V is killed by Stmt S in Block B, add S:V pair to EB->Kill.
324+
// If variable V is killed by Stmt S in Block B, add TopLevelStmt:V pair
325+
// to EB->Kill, where TopLevelStmt is the top-level Stmt that contains S.
318326
// @param[in] EB is the ElevatedCFGBlock for the current block.
327+
// @param[in] TopLevelStmt is the top-level Stmt in the block.
319328
// @param[in] S is the current Stmt in the block.
320-
void FillKillSet(ElevatedCFGBlock *EB, const Stmt *S);
329+
void FillKillSet(ElevatedCFGBlock *EB, const Stmt *TopLevelStmt, const Stmt *S);
321330

322331
// Initialize the In and Out sets for all blocks, except the Entry block,
323332
// as Top.

clang/include/clang/Sema/Sema.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5186,7 +5186,8 @@ class Sema {
51865186

51875187
enum BoundsDeclarationCheck {
51885188
BDC_Assignment,
5189-
BDC_Initialization
5189+
BDC_Initialization,
5190+
BDC_Statement
51905191
};
51915192

51925193
/// \brief Check that address=of operation is not taking the
@@ -5213,6 +5214,12 @@ class Sema {
52135214
// will always fail.
52145215
void WarnDynamicCheckAlwaysFails(const Expr *Condition);
52155216

5217+
// If the VarDecl D has a byte_count or count bounds expression,
5218+
// NormalizeBounds expands it to a range bounds expression. The expanded
5219+
// range bounds are attached to the VarDecl D to avoid recomputing the
5220+
// normalized bounds for D.
5221+
BoundsExpr *NormalizeBounds(const VarDecl *D);
5222+
52165223
// This is wrapper around CheckBoundsDeclaration::ExpandToRange. This
52175224
// provides an easy way to invoke this function from outside the class. Given
52185225
// a byte_count or count bounds expression for the VarDecl D, ExpandToRange

clang/lib/AST/ASTContext.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8804,7 +8804,9 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
88048804
// For unchecked return types, a return with
88058805
// bounds is compatible with a return without bounds.
88068806
// The merged type includes the bounds.
8807-
if (!retType->isUncheckedPointerType())
8807+
// Ignore the error if we do not want to consider checked pointers.
8808+
if (!retType->isUncheckedPointerType() &&
8809+
!getLangOpts().CheckedCConverter)
88088810
return QualType();
88098811
if (!lReturnAnnots.IsEmpty() && rReturnAnnots.IsEmpty()) {
88108812
ReturnAnnots = lReturnAnnots;
@@ -8858,7 +8860,9 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
88588860
// For unchecked parameter types, a parameter with
88598861
// bounds is compatible with a parameter without bounds.
88608862
// The merged type includes the bounds.
8861-
if (!paramType->isUncheckedPointerType())
8863+
// Ignored the error if we do not want to consider checked pointers.
8864+
if (!paramType->isUncheckedPointerType() &&
8865+
!getLangOpts().CheckedCConverter)
88628866
return QualType();
88638867
if (!lBounds.IsEmpty() && rBounds.IsEmpty()) {
88648868
bounds.push_back(lBounds);

clang/lib/AST/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ add_clang_library(clangAST
5656
OSLog.cpp
5757
OpenMPClause.cpp
5858
ParentMap.cpp
59+
PreorderAST.cpp
5960
PrintfFormatString.cpp
6061
QualTypeNames.cpp
6162
RawCommentList.cpp

0 commit comments

Comments
 (0)