Skip to content

Commit ef1f74c

Browse files
authored
Merge branch 'main' into mlem
2 parents 9d1280c + dd44e63 commit ef1f74c

File tree

30 files changed

+503
-277
lines changed

30 files changed

+503
-277
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,8 @@ C23 Feature Support
191191
- Added ``FLT_SNAN``, ``DBL_SNAN``, and ``LDBL_SNAN`` to Clang's ``<float.h>``
192192
header in C23 and later modes. This implements
193193
`WG14 N2710 <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2710.htm>`_.
194+
- Fixed accepting as compatible unnamed tag types with the same fields within
195+
the same translation unit but from different types.
194196

195197
Non-comprehensive list of changes in this release
196198
-------------------------------------------------

clang/lib/AST/ASTContext.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11581,6 +11581,12 @@ QualType ASTContext::mergeTagDefinitions(QualType LHS, QualType RHS) {
1158111581
if (LangOpts.CPlusPlus || !LangOpts.C23)
1158211582
return {};
1158311583

11584+
// Nameless tags are comparable only within outer definitions. At the top
11585+
// level they are not comparable.
11586+
const TagDecl *LTagD = LHS->castAsTagDecl(), *RTagD = RHS->castAsTagDecl();
11587+
if (!LTagD->getIdentifier() || !RTagD->getIdentifier())
11588+
return {};
11589+
1158411590
// C23, on the other hand, requires the members to be "the same enough", so
1158511591
// we use a structural equivalence check.
1158611592
StructuralEquivalenceContext::NonEquivalentDeclSet NonEquivalentDecls;

clang/lib/AST/ASTStructuralEquivalence.cpp

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1763,19 +1763,6 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
17631763
// another anonymous structure or union, respectively, if their members
17641764
// fulfill the preceding requirements. ... Otherwise, the structure, union,
17651765
// or enumerated types are incompatible.
1766-
1767-
// Note: "the same tag" refers to the identifier for the structure; two
1768-
// structures without names are not compatible within a TU. In C23, if either
1769-
// declaration has no name, they're not equivalent. However, the paragraph
1770-
// after the bulleted list goes on to talk about compatibility of anonymous
1771-
// structure and union members, so this prohibition only applies to top-level
1772-
// declarations; if either declaration is not a member, they cannot be
1773-
// compatible.
1774-
if (Context.LangOpts.C23 && (!D1->getIdentifier() || !D2->getIdentifier()) &&
1775-
(!D1->getDeclContext()->isRecord() || !D2->getDeclContext()->isRecord()))
1776-
return false;
1777-
1778-
// Otherwise, check the names for equivalence.
17791766
if (!NameIsStructurallyEquivalent(*D1, *D2))
17801767
return false;
17811768

clang/lib/CIR/CodeGen/CIRGenStmt.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,7 @@ mlir::LogicalResult CIRGenFunction::emitLabel(const clang::LabelDecl &d) {
536536
mlir::Block *currBlock = builder.getBlock();
537537
mlir::Block *labelBlock = currBlock;
538538

539-
if (!currBlock->empty()) {
539+
if (!currBlock->empty() || currBlock->isEntryBlock()) {
540540
{
541541
mlir::OpBuilder::InsertionGuard guard(builder);
542542
labelBlock = builder.createBlock(builder.getBlock()->getParent());

clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ bool tryToFindPtrOrigin(
2626
const Expr *E, bool StopAtFirstRefCountedObj,
2727
std::function<bool(const clang::CXXRecordDecl *)> isSafePtr,
2828
std::function<bool(const clang::QualType)> isSafePtrType,
29+
std::function<bool(const clang::Decl *)> isSafeGlobalDecl,
2930
std::function<bool(const clang::Expr *, bool)> callback) {
3031
while (E) {
3132
if (auto *DRE = dyn_cast<DeclRefExpr>(E)) {
@@ -34,6 +35,8 @@ bool tryToFindPtrOrigin(
3435
auto IsImmortal = safeGetName(VD) == "NSApp";
3536
if (VD->hasGlobalStorage() && (IsImmortal || QT.isConstQualified()))
3637
return callback(E, true);
38+
if (VD->hasGlobalStorage() && isSafeGlobalDecl(VD))
39+
return callback(E, true);
3740
}
3841
}
3942
if (auto *tempExpr = dyn_cast<MaterializeTemporaryExpr>(E)) {
@@ -71,9 +74,11 @@ bool tryToFindPtrOrigin(
7174
}
7275
if (auto *Expr = dyn_cast<ConditionalOperator>(E)) {
7376
return tryToFindPtrOrigin(Expr->getTrueExpr(), StopAtFirstRefCountedObj,
74-
isSafePtr, isSafePtrType, callback) &&
77+
isSafePtr, isSafePtrType, isSafeGlobalDecl,
78+
callback) &&
7579
tryToFindPtrOrigin(Expr->getFalseExpr(), StopAtFirstRefCountedObj,
76-
isSafePtr, isSafePtrType, callback);
80+
isSafePtr, isSafePtrType, isSafeGlobalDecl,
81+
callback);
7782
}
7883
if (auto *cast = dyn_cast<CastExpr>(E)) {
7984
if (StopAtFirstRefCountedObj) {

clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ bool tryToFindPtrOrigin(
5656
const clang::Expr *E, bool StopAtFirstRefCountedObj,
5757
std::function<bool(const clang::CXXRecordDecl *)> isSafePtr,
5858
std::function<bool(const clang::QualType)> isSafePtrType,
59+
std::function<bool(const clang::Decl *)> isSafeGlobalDecl,
5960
std::function<bool(const clang::Expr *, bool)> callback);
6061

6162
/// For \p E referring to a ref-countable/-counted pointer/reference we return

clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefCallArgsChecker.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@ namespace {
2929
class RawPtrRefCallArgsChecker
3030
: public Checker<check::ASTDecl<TranslationUnitDecl>> {
3131
BugType Bug;
32-
mutable BugReporter *BR;
3332

3433
TrivialFunctionAnalysis TFA;
3534
EnsureFunctionAnalysis EFA;
3635

3736
protected:
37+
mutable BugReporter *BR;
3838
mutable std::optional<RetainTypeChecker> RTC;
3939

4040
public:
@@ -46,6 +46,7 @@ class RawPtrRefCallArgsChecker
4646
virtual bool isSafePtr(const CXXRecordDecl *Record) const = 0;
4747
virtual bool isSafePtrType(const QualType type) const = 0;
4848
virtual bool isSafeExpr(const Expr *) const { return false; }
49+
virtual bool isSafeDecl(const Decl *) const { return false; }
4950
virtual const char *ptrKind() const = 0;
5051

5152
void checkASTDecl(const TranslationUnitDecl *TUD, AnalysisManager &MGR,
@@ -214,6 +215,7 @@ class RawPtrRefCallArgsChecker
214215
Arg, /*StopAtFirstRefCountedObj=*/true,
215216
[&](const clang::CXXRecordDecl *Record) { return isSafePtr(Record); },
216217
[&](const clang::QualType T) { return isSafePtrType(T); },
218+
[&](const clang::Decl *D) { return isSafeDecl(D); },
217219
[&](const clang::Expr *ArgOrigin, bool IsSafe) {
218220
if (IsSafe)
219221
return true;
@@ -479,6 +481,11 @@ class UnretainedCallArgsChecker final : public RawPtrRefCallArgsChecker {
479481
isa<ObjCMessageExpr>(E);
480482
}
481483

484+
bool isSafeDecl(const Decl *D) const final {
485+
// Treat NS/CF globals in system header as immortal.
486+
return BR->getSourceManager().isInSystemHeader(D->getLocation());
487+
}
488+
482489
const char *ptrKind() const final { return "unretained"; }
483490
};
484491

clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLocalVarsChecker.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,10 +166,10 @@ bool isGuardedScopeEmbeddedInGuardianScope(const VarDecl *Guarded,
166166
class RawPtrRefLocalVarsChecker
167167
: public Checker<check::ASTDecl<TranslationUnitDecl>> {
168168
BugType Bug;
169-
mutable BugReporter *BR;
170169
EnsureFunctionAnalysis EFA;
171170

172171
protected:
172+
mutable BugReporter *BR;
173173
mutable std::optional<RetainTypeChecker> RTC;
174174

175175
public:
@@ -180,6 +180,7 @@ class RawPtrRefLocalVarsChecker
180180
virtual bool isSafePtr(const CXXRecordDecl *) const = 0;
181181
virtual bool isSafePtrType(const QualType) const = 0;
182182
virtual bool isSafeExpr(const Expr *) const { return false; }
183+
virtual bool isSafeDecl(const Decl *) const { return false; }
183184
virtual const char *ptrKind() const = 0;
184185

185186
void checkASTDecl(const TranslationUnitDecl *TUD, AnalysisManager &MGR,
@@ -288,6 +289,7 @@ class RawPtrRefLocalVarsChecker
288289
return isSafePtr(Record);
289290
},
290291
[&](const clang::QualType Type) { return isSafePtrType(Type); },
292+
[&](const clang::Decl *D) { return isSafeDecl(D); },
291293
[&](const clang::Expr *InitArgOrigin, bool IsSafe) {
292294
if (!InitArgOrigin || IsSafe)
293295
return true;
@@ -443,6 +445,10 @@ class UnretainedLocalVarsChecker final : public RawPtrRefLocalVarsChecker {
443445
return ento::cocoa::isCocoaObjectRef(E->getType()) &&
444446
isa<ObjCMessageExpr>(E);
445447
}
448+
bool isSafeDecl(const Decl *D) const final {
449+
// Treat NS/CF globals in system header as immortal.
450+
return BR->getSourceManager().isInSystemHeader(D->getLocation());
451+
}
446452
const char *ptrKind() const final { return "unretained"; }
447453
};
448454

clang/test/Analysis/Checkers/WebKit/mock-system-header.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,17 @@ void os_log_msg(os_log_t oslog, os_log_type_t type, const char *msg, ...);
3434

3535
typedef const struct __attribute__((objc_bridge(NSString))) __CFString * CFStringRef;
3636

37+
extern CFStringRef const kCFURLTagNamesKey;
38+
3739
#ifdef __OBJC__
3840
@class NSString;
3941
@interface SystemObject {
4042
NSString *ns_string;
4143
CFStringRef cf_string;
4244
}
4345
@end
46+
47+
typedef NSString *NSNotificationName;
48+
extern "C" NSNotificationName NSApplicationDidBecomeActiveNotification;
49+
4450
#endif

clang/test/Analysis/Checkers/WebKit/unretained-local-vars.mm

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UnretainedLocalVarsChecker -verify %s
22

33
#import "objc-mock-types.h"
4+
#import "mock-system-header.h"
45

56
void someFunction();
7+
extern "C" CFStringRef LocalGlobalCFString;
8+
extern "C" NSString *LocalGlobalNSString;
69

710
namespace raw_ptr {
811
void foo() {
@@ -547,6 +550,29 @@ void foo() {
547550

548551
} // autoreleased
549552

553+
namespace ns_global {
554+
555+
void consumeCFString(CFStringRef);
556+
void consumeNSString(NSString *);
557+
558+
void cf() {
559+
auto *str = kCFURLTagNamesKey;
560+
consumeCFString(str);
561+
auto *localStr = LocalGlobalCFString;
562+
// expected-warning@-1{{Local variable 'localStr' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}
563+
consumeCFString(localStr);
564+
}
565+
566+
void ns() {
567+
auto *str = NSApplicationDidBecomeActiveNotification;
568+
consumeNSString(str);
569+
auto *localStr = LocalGlobalNSString;
570+
// expected-warning@-1{{Local variable 'localStr' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}
571+
consumeNSString(localStr);
572+
}
573+
574+
}
575+
550576
bool doMoreWorkOpaque(OtherObj*);
551577
SomeObj* provide();
552578

0 commit comments

Comments
 (0)