Skip to content

Commit

Permalink
merge internal development externally
Browse files Browse the repository at this point in the history
  • Loading branch information
searlmc1 committed May 28, 2024
2 parents c408a4c + 90dc7f8 commit 5adaf6a
Show file tree
Hide file tree
Showing 252 changed files with 13,423 additions and 7,341 deletions.
1 change: 0 additions & 1 deletion clang-tools-extra/clang-tidy/misc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ add_clang_library(clangTidyMiscModule
genconfusable
ClangDriverOptions
)
set_target_properties(clangTidyMiscModule PROPERTIES FOLDER "Clang Tools Extra/Libraries")

clang_target_link_libraries(clangTidyMiscModule
PRIVATE
Expand Down
5 changes: 5 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,8 @@ Bug Fixes in This Version
Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

- Fix crash when atomic builtins are called with pointer to zero-size struct (#GH90330)

Bug Fixes to Attribute Support
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down Expand Up @@ -802,6 +804,9 @@ Bug Fixes to C++ Support
in dependent contexts. Fixes (#GH92680).
- Fixed a crash when diagnosing failed conversions involving template parameter
packs. (#GH93076)
- Fixed a regression introduced in Clang 18 causing a static function overloading a non-static function
with the same parameters not to be diagnosed. (Fixes #GH93456).
- Clang now diagnoses unexpanded parameter packs in attributes. (Fixes #GH93269).

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
6 changes: 4 additions & 2 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -855,7 +855,7 @@ def note_strncat_wrong_size : Note<
"the terminating null byte">;

def warn_assume_side_effects : Warning<
"the argument to %0 has side effects that will be discarded">,
"assumption is ignored because it contains (potential) side-effects">,
InGroup<DiagGroup<"assume">>;
def warn_omp_assume_attribute_string_unknown : Warning<
"unknown assumption string '%0'; attribute is potentially ignored">,
Expand Down Expand Up @@ -8860,8 +8860,10 @@ def err_builtin_fn_use : Error<"builtin functions must be directly called">;

def warn_call_wrong_number_of_arguments : Warning<
"too %select{few|many}0 arguments in call to %1">;

def err_atomic_builtin_must_be_pointer : Error<
"address argument to atomic builtin must be a pointer (%0 invalid)">;
"address argument to atomic builtin must be a pointer %select{|to a non-zero-sized object }1(%0 invalid)">;

def err_atomic_builtin_must_be_pointer_intptr : Error<
"address argument to atomic builtin must be a pointer to integer or pointer"
" (%0 invalid)">;
Expand Down
10 changes: 7 additions & 3 deletions clang/lib/AST/Interp/ByteCodeExprGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2672,6 +2672,9 @@ bool ByteCodeExprGen<Emitter>::delegate(const Expr *E) {
}

template <class Emitter> bool ByteCodeExprGen<Emitter>::visit(const Expr *E) {
if (E->getType().isNull())
return false;

if (E->getType()->isVoidType())
return this->discard(E);

Expand Down Expand Up @@ -3338,7 +3341,8 @@ bool ByteCodeExprGen<Emitter>::VisitCallExpr(const CallExpr *E) {
// write the result into.
if (IsVirtual && !HasQualifier) {
uint32_t VarArgSize = 0;
unsigned NumParams = Func->getNumWrittenParams();
unsigned NumParams =
Func->getNumWrittenParams() + isa<CXXOperatorCallExpr>(E);
for (unsigned I = NumParams, N = E->getNumArgs(); I != N; ++I)
VarArgSize += align(primSize(classify(E->getArg(I)).value_or(PT_Ptr)));

Expand Down Expand Up @@ -3772,13 +3776,13 @@ bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) {
return this->emitGetPtrLocal(Offset, E);
} else if (auto GlobalIndex = P.getGlobal(D)) {
if (IsReference)
return this->emitGetGlobalPtr(*GlobalIndex, E);
return this->emitGetGlobal(classifyPrim(E), *GlobalIndex, E);

return this->emitGetPtrGlobal(*GlobalIndex, E);
} else if (const auto *PVD = dyn_cast<ParmVarDecl>(D)) {
if (auto It = this->Params.find(PVD); It != this->Params.end()) {
if (IsReference || !It->second.IsPtr)
return this->emitGetParamPtr(It->second.Offset, E);
return this->emitGetParam(classifyPrim(E), It->second.Offset, E);

return this->emitGetPtrParam(It->second.Offset, E);
}
Expand Down
28 changes: 14 additions & 14 deletions clang/lib/AST/Interp/PrimType.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,20 @@ template <unsigned Bits, bool Signed> class Integral;

/// Enumeration of the primitive types of the VM.
enum PrimType : unsigned {
PT_Sint8,
PT_Uint8,
PT_Sint16,
PT_Uint16,
PT_Sint32,
PT_Uint32,
PT_Sint64,
PT_Uint64,
PT_IntAP,
PT_IntAPS,
PT_Bool,
PT_Float,
PT_Ptr,
PT_FnPtr,
PT_Sint8 = 0,
PT_Uint8 = 1,
PT_Sint16 = 2,
PT_Uint16 = 3,
PT_Sint32 = 4,
PT_Uint32 = 5,
PT_Sint64 = 6,
PT_Uint64 = 7,
PT_IntAP = 8,
PT_IntAPS = 9,
PT_Bool = 10,
PT_Float = 11,
PT_Ptr = 12,
PT_FnPtr = 13,
};

inline constexpr bool isPtrType(PrimType T) {
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,11 @@ bool Parser::ParseAttributeArgumentList(
break;
}

if (Actions.DiagnoseUnexpandedParameterPack(Expr.get())) {
SawError = true;
break;
}

Exprs.push_back(Expr.get());

if (Tok.isNot(tok::comma))
Expand Down
17 changes: 12 additions & 5 deletions clang/lib/Sema/SemaChecking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3824,7 +3824,7 @@ bool Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall,
const PointerType *pointerType = PointerArg->getType()->getAs<PointerType>();
if (!pointerType) {
Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer)
<< PointerArg->getType() << PointerArg->getSourceRange();
<< PointerArg->getType() << 0 << PointerArg->getSourceRange();
return true;
}

Expand Down Expand Up @@ -3858,7 +3858,7 @@ bool Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall,
if (!ValType->isIntegerType() && !ValType->isAnyPointerType() &&
!ValType->isBlockPointerType() && !ValType->isFloatingType()) {
Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer_intfltptr)
<< PointerArg->getType() << PointerArg->getSourceRange();
<< PointerArg->getType() << 0 << PointerArg->getSourceRange();
return true;
}

Expand Down Expand Up @@ -6803,7 +6803,7 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
const PointerType *pointerType = Ptr->getType()->getAs<PointerType>();
if (!pointerType) {
Diag(ExprRange.getBegin(), diag::err_atomic_builtin_must_be_pointer)
<< Ptr->getType() << Ptr->getSourceRange();
<< Ptr->getType() << 0 << Ptr->getSourceRange();
return ExprError();
}

Expand Down Expand Up @@ -6832,6 +6832,13 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
}
}

// Pointer to object of size zero is not allowed.
if (Context.getTypeInfoInChars(AtomTy).Width.isZero()) {
Diag(ExprRange.getBegin(), diag::err_atomic_builtin_must_be_pointer)
<< Ptr->getType() << 1 << Ptr->getSourceRange();
return ExprError();
}

// For an arithmetic operation, the implied arithmetic must be well-formed.
if (Form == Arithmetic) {
// GCC does not enforce these rules for GNU atomics, but we do to help catch
Expand Down Expand Up @@ -7223,15 +7230,15 @@ ExprResult Sema::BuiltinAtomicOverloaded(ExprResult TheCallResult) {
const PointerType *pointerType = FirstArg->getType()->getAs<PointerType>();
if (!pointerType) {
Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer)
<< FirstArg->getType() << FirstArg->getSourceRange();
<< FirstArg->getType() << 0 << FirstArg->getSourceRange();
return ExprError();
}

QualType ValType = pointerType->getPointeeType();
if (!ValType->isIntegerType() && !ValType->isAnyPointerType() &&
!ValType->isBlockPointerType()) {
Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer_intptr)
<< FirstArg->getType() << FirstArg->getSourceRange();
<< FirstArg->getType() << 0 << FirstArg->getSourceRange();
return ExprError();
}

Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Sema/SemaOverload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1482,7 +1482,7 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, FunctionDecl *New,
}

if (OldMethod && NewMethod && !OldMethod->isStatic() &&
!OldMethod->isStatic()) {
!NewMethod->isStatic()) {
bool HaveCorrespondingObjectParameters = [&](const CXXMethodDecl *Old,
const CXXMethodDecl *New) {
auto NewObjectType = New->getFunctionObjectParameterReferenceType();
Expand Down Expand Up @@ -14363,7 +14363,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
if (Fn.isInvalid())
return ExprError();
return CXXOperatorCallExpr::Create(Context, Op, Fn.get(), ArgsArray,
Context.DependentTy, VK, OpLoc,
Context.DependentTy, VK_PRValue, OpLoc,
CurFPFeatureOverrides());
}

Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Sema/SemaTemplateVariadic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ namespace {

bool shouldWalkTypesOfTypeLocs() const { return false; }

// We need this so we can find e.g. attributes on lambdas.
bool shouldVisitImplicitCode() const { return true; }

//------------------------------------------------------------------------
// Recording occurrences of (unexpanded) parameter packs.
//------------------------------------------------------------------------
Expand Down
6 changes: 6 additions & 0 deletions clang/test/AST/Interp/functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -623,3 +623,9 @@ namespace FuncPtrParam {
*a; // both-warning {{expression result unused}}
}
}

namespace {
void f() noexcept;
void (&r)() = f;
void (&cond3)() = r;
}
13 changes: 13 additions & 0 deletions clang/test/AST/Interp/records.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1467,3 +1467,16 @@ namespace IgnoredCtorWithZeroInit {
return (S(), true);
}
}

#if __cplusplus >= 202002L
namespace VirtOperator {
/// This used to crash because it's a virtual CXXOperatorCallExpr.
struct B {
virtual constexpr bool operator==(const B&) const { return true; }
};
struct D : B {
constexpr bool operator==(const B&) const override{ return false; } // both-note {{operator}}
};
constexpr bool cmp_base_derived = D() == D(); // both-warning {{ambiguous}}
}
#endif
2 changes: 1 addition & 1 deletion clang/test/Parser/MicrosoftExtensions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ bool f(int);
template <typename T>
struct A {
constexpr A(T t) {
__assume(f(t)); // expected-warning{{the argument to '__assume' has side effects that will be discarded}}
__assume(f(t)); // expected-warning{{assumption is ignored because it contains (potential) side-effects}}
}
constexpr bool g() { return false; }
};
Expand Down
32 changes: 32 additions & 0 deletions clang/test/Sema/atomic-ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,38 @@ void memory_checks(_Atomic(int) *Ap, int *p, int val) {
(void)__atomic_compare_exchange_n(p, p, val, 0, memory_order_seq_cst, -1); // expected-warning {{memory order argument to atomic operation is invalid}}
}

struct Z {
char z[];
};

void zeroSizeArgError(struct Z *a, struct Z *b, struct Z *c) {
__atomic_exchange(b, b, c, memory_order_relaxed); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}}
__atomic_exchange(b, b, c, memory_order_acq_rel); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}}
__atomic_exchange(b, b, c, memory_order_acquire); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}}
__atomic_exchange(b, b, c, memory_order_consume); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}}
__atomic_exchange(b, b, c, memory_order_release); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}}
__atomic_exchange(b, b, c, memory_order_seq_cst); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}}
__atomic_load(a, b, memory_order_relaxed); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}}
__atomic_load(a, b, memory_order_acq_rel); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}}
__atomic_load(a, b, memory_order_acquire); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}}
__atomic_load(a, b, memory_order_consume); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}}
__atomic_load(a, b, memory_order_release); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}}
__atomic_load(a, b, memory_order_seq_cst); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}}
__atomic_store(a, b, memory_order_relaxed); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}}
__atomic_store(a, b, memory_order_acq_rel); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}}
__atomic_store(a, b, memory_order_acquire); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}}
__atomic_store(a, b, memory_order_consume); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}}
__atomic_store(a, b, memory_order_release); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}}
__atomic_store(a, b, memory_order_seq_cst); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}}
__atomic_compare_exchange(a, b, c, 0, memory_order_relaxed, memory_order_relaxed); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}}
__atomic_compare_exchange(a, b, c, 0, memory_order_acq_rel, memory_order_acq_rel); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}}
__atomic_compare_exchange(a, b, c, 0, memory_order_acquire, memory_order_acquire); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}}
__atomic_compare_exchange(a, b, c, 0, memory_order_consume, memory_order_consume); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}}
__atomic_compare_exchange(a, b, c, 0, memory_order_release, memory_order_release); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}}
__atomic_compare_exchange(a, b, c, 0, memory_order_seq_cst, memory_order_seq_cst); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}}

}

void nullPointerWarning(void) {
volatile _Atomic(int) vai;
_Atomic(int) ai;
Expand Down
12 changes: 6 additions & 6 deletions clang/test/Sema/builtin-assume.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,20 @@ int ispure(int) __attribute__((pure));
int foo(int *a, int i) {
#ifdef _MSC_VER
__assume(i != 4);
__assume(++i > 2); //expected-warning {{the argument to '__assume' has side effects that will be discarded}}
__assume(nonconst() > 2); //expected-warning {{the argument to '__assume' has side effects that will be discarded}}
__assume(++i > 2); //expected-warning {{assumption is ignored because it contains (potential) side-effects}}
__assume(nonconst() > 2); //expected-warning {{assumption is ignored because it contains (potential) side-effects}}
__assume(isconst() > 2);
__assume(ispure(i) > 2);
__assume(ispure(++i) > 2); //expected-warning {{the argument to '__assume' has side effects that will be discarded}}
__assume(ispure(++i) > 2); //expected-warning {{assumption is ignored because it contains (potential) side-effects}}

int test = sizeof(struct{char qq[(__assume(i != 5), 7)];});
#else
__builtin_assume(i != 4);
__builtin_assume(++i > 2); //expected-warning {{the argument to '__builtin_assume' has side effects that will be discarded}}
__builtin_assume(nonconst() > 2); //expected-warning {{the argument to '__builtin_assume' has side effects that will be discarded}}
__builtin_assume(++i > 2); //expected-warning {{assumption is ignored because it contains (potential) side-effects}}
__builtin_assume(nonconst() > 2); //expected-warning {{assumption is ignored because it contains (potential) side-effects}}
__builtin_assume(isconst() > 2);
__builtin_assume(ispure(i) > 2);
__builtin_assume(ispure(++i) > 2); //expected-warning {{the argument to '__builtin_assume' has side effects that will be discarded}}
__builtin_assume(ispure(++i) > 2); //expected-warning {{assumption is ignored because it contains (potential) side-effects}}

int test = sizeof(struct{char qq[(__builtin_assume(i != 5), 7)];}); // expected-warning {{variable length array}}
#endif
Expand Down
2 changes: 1 addition & 1 deletion clang/test/Sema/stmtexprs.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ int stmtexpr_fn(void);
void stmtexprs(int i) {
__builtin_assume( ({ 1; }) ); // no warning about "side effects"
__builtin_assume( ({ if (i) { (void)0; }; 42; }) ); // no warning about "side effects"
// expected-warning@+1 {{the argument to '__builtin_assume' has side effects that will be discarded}}
// expected-warning@+1 {{assumption is ignored because it contains (potential) side-effects}}
__builtin_assume( ({ if (i) ({ stmtexpr_fn(); }); 1; }) );
}
20 changes: 20 additions & 0 deletions clang/test/SemaCXX/attribute-pack-expansion.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s

template <bool... vals>
void f() __attribute((diagnose_if(vals, "message", "error"))) { // expected-error {{expression contains unexpanded parameter pack 'vals'}}
[] () __attribute((diagnose_if(vals, "message", "error"))) {}(); // expected-error {{expression contains unexpanded parameter pack 'vals'}}
[] () __attribute((diagnose_if(vals..., "message", "error"))) {}(); // expected-error {{attribute 'diagnose_if' does not support argument pack expansion}}
[] <bool ...inner> () __attribute((diagnose_if(inner, "message", "error"))) {}(); // expected-error {{expression contains unexpanded parameter pack 'inner'}}
([] <bool ...inner> () __attribute((diagnose_if(inner, "message", "error"))) {}(), ...); // expected-error {{expression contains unexpanded parameter pack 'inner'}} \
// expected-error {{pack expansion does not contain any unexpanded parameter packs}}

// This is fine, so check that we're actually emitting an error
// due to the 'diagnose_if'.
([] () __attribute((diagnose_if(vals, "foobar", "error"))) {}(), ...); // expected-error {{foobar}} expected-note {{from 'diagnose_if'}}
}

void g() {
f<>();
f<false>();
f<true, true>(); // expected-note {{in instantiation of}}
}
Loading

0 comments on commit 5adaf6a

Please sign in to comment.