[clang] [Clang] support storage-class specifiers in C23 compound literals (PR #212559)
Oleksandr Tarasiuk via cfe-commits
cfe-commits at lists.llvm.org
Sun Sep 13 12:19:16 PDT 2026
https://github.com/a-tarasyuk updated https://github.com/llvm/llvm-project/pull/212559
>From 0c41fd3fcbbdd487201d26a0fbadbebf24c4b669 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk <oleksandr.tarasiuk at outlook.com>
Date: Tue, 28 Jul 2026 17:14:33 +0300
Subject: [PATCH 01/21] [Clang] support storage-class specifiers in C23
compound literals
---
clang/docs/ReleaseNotes.md | 2 +
clang/include/clang/AST/Expr.h | 66 +++-
clang/include/clang/AST/Stmt.h | 17 +
.../clang/Basic/DiagnosticParseKinds.td | 4 +
.../clang/Basic/DiagnosticSemaKinds.td | 18 +-
clang/include/clang/Parse/Parser.h | 6 +-
clang/include/clang/Sema/DelayedDiagnostic.h | 15 +-
clang/include/clang/Sema/Initialization.h | 24 +-
clang/include/clang/Sema/Scope.h | 6 +-
clang/include/clang/Sema/Sema.h | 24 +-
clang/lib/AST/ASTImporter.cpp | 6 +-
clang/lib/AST/Expr.cpp | 9 +-
clang/lib/AST/ExprConstant.cpp | 93 +++--
clang/lib/AST/StmtPrinter.cpp | 24 +-
clang/lib/AST/StmtProfile.cpp | 3 +
clang/lib/CodeGen/CGExpr.cpp | 17 +-
clang/lib/CodeGen/CGExprAgg.cpp | 7 +-
clang/lib/CodeGen/CGExprConstant.cpp | 10 +-
clang/lib/CodeGen/CodeGenFunction.cpp | 4 +-
clang/lib/Parse/ParseExpr.cpp | 98 ++++-
clang/lib/Sema/CheckExprLifetime.cpp | 3 +-
clang/lib/Sema/DelayedDiagnostic.cpp | 1 +
clang/lib/Sema/Scope.cpp | 15 +-
clang/lib/Sema/SemaDecl.cpp | 39 +-
clang/lib/Sema/SemaDeclAttr.cpp | 8 +
clang/lib/Sema/SemaExpr.cpp | 370 ++++++++++++------
clang/lib/Sema/SemaInit.cpp | 45 ++-
clang/lib/Sema/TreeTransform.h | 18 +-
clang/lib/Serialization/ASTReaderStmt.cpp | 3 +
clang/lib/Serialization/ASTWriterStmt.cpp | 3 +
clang/test/AST/c23-compound-literal-print.c | 33 ++
clang/test/C/drs/dr3xx.c | 1 +
clang/test/CodeGen/c23-compound-literal.c | 275 +++++++++++++
clang/test/CodeGenObjC/c23-compound-literal.m | 19 +
clang/test/Parser/expressions.c | 18 +-
clang/test/Sema/c23-compound-literal.c | 343 ++++++++++++++++
clang/test/Sema/c23-compound-literal.m | 11 +
clang/test/Sema/constexpr.c | 2 +-
38 files changed, 1418 insertions(+), 242 deletions(-)
create mode 100644 clang/test/AST/c23-compound-literal-print.c
create mode 100644 clang/test/CodeGen/c23-compound-literal.c
create mode 100644 clang/test/CodeGenObjC/c23-compound-literal.m
create mode 100644 clang/test/Sema/c23-compound-literal.c
create mode 100644 clang/test/Sema/c23-compound-literal.m
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index c348ddaf23017..bd7689b2fc3c3 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -142,6 +142,8 @@ features cannot lower the translation-unit ABI level;
#### C23 Feature Support
+- Clang now supports storage-class specifiers in compound literals. (#GH129365)
+
### Objective-C Language Changes
### Non-comprehensive list of changes in this release
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index f95f87cc4e8e0..6454a750b61c9 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -765,6 +765,8 @@ class Expr : public ValueStmt {
/// evaluation is not part of the evaluation, but all other temporaries
/// are destroyed.
ImmediateInvocation,
+ /// The initializer of a compound literal constant.
+ CompoundLiteralInitializer,
};
/// Evaluate an expression that is required to be a constant expression. Does
@@ -3606,7 +3608,7 @@ class MemberExpr final
}
};
-/// CompoundLiteralExpr - [C99 6.5.2.5]
+/// CompoundLiteralExpr - [C99 6.5.2.5, C23 6.5.3.6]
///
class CompoundLiteralExpr : public Expr {
/// LParenLoc - If non-null, this is the location of the left paren in a
@@ -3624,11 +3626,20 @@ class CompoundLiteralExpr : public Expr {
mutable APValue *StaticValue = nullptr;
public:
- CompoundLiteralExpr(SourceLocation lparenloc, TypeSourceInfo *tinfo,
- QualType T, ExprValueKind VK, Expr *init, bool fileScope)
+ CompoundLiteralExpr(
+ SourceLocation LParenLoc, TypeSourceInfo *TInfo, QualType T,
+ ExprValueKind VK, Expr *Init, bool FileScope, StorageClass SC = SC_None,
+ ThreadStorageClassSpecifier TSC = TSCS_unspecified,
+ ConstexprSpecKind ConstexprKind = ConstexprSpecKind::Unspecified)
: Expr(CompoundLiteralExprClass, T, VK, OK_Ordinary),
- LParenLoc(lparenloc), TInfoAndScope(tinfo, fileScope), Init(init) {
+ LParenLoc(LParenLoc), TInfoAndScope(TInfo, FileScope), Init(Init) {
assert(Init && "Init is a nullptr");
+ assert((ConstexprKind == ConstexprSpecKind::Unspecified ||
+ ConstexprKind == ConstexprSpecKind::Constexpr) &&
+ "invalid compound literal constexpr specifier");
+ setStorageClass(SC);
+ setTSCSpec(TSC);
+ setConstexpr(ConstexprKind == ConstexprSpecKind::Constexpr);
setDependence(computeDependence(this));
}
@@ -3649,11 +3660,52 @@ class CompoundLiteralExpr : public Expr {
TypeSourceInfo *getTypeSourceInfo() const {
return TInfoAndScope.getPointer();
}
- void setTypeSourceInfo(TypeSourceInfo *tinfo) {
- TInfoAndScope.setPointer(tinfo);
+
+ void setTypeSourceInfo(TypeSourceInfo *TInfo) {
+ TInfoAndScope.setPointer(TInfo);
+ }
+
+ bool hasStaticStorage() const {
+ return isGLValue() && !hasThreadStorage() &&
+ (isFileScope() || getStorageClass() == SC_Static);
+ }
+
+ bool hasThreadStorage() const { return getTSCSpec() != TSCS_unspecified; }
+
+ bool hasGlobalStorage() const {
+ return hasStaticStorage() || hasThreadStorage();
+ }
+
+ StorageClass getStorageClass() const {
+ return static_cast<StorageClass>(CompoundLiteralExprBits.SClass);
+ }
+
+ void setStorageClass(StorageClass SC) {
+ assert((SC == SC_None || SC == SC_Static || SC == SC_Register) &&
+ "invalid compound literal storage class");
+ CompoundLiteralExprBits.SClass = SC;
+ assert(getStorageClass() == SC && "truncation");
+ }
+
+ ThreadStorageClassSpecifier getTSCSpec() const {
+ return static_cast<ThreadStorageClassSpecifier>(
+ CompoundLiteralExprBits.TSCSpec);
+ }
+
+ void setTSCSpec(ThreadStorageClassSpecifier TSC) {
+ assert((TSC == TSCS_unspecified || TSC == TSCS_thread_local ||
+ TSC == TSCS__Thread_local) &&
+ "invalid compound literal thread storage class");
+ CompoundLiteralExprBits.TSCSpec = TSC;
+ assert(getTSCSpec() == TSC && "truncation");
+ }
+
+ bool isConstexpr() const { return CompoundLiteralExprBits.IsConstexpr; }
+
+ void setConstexpr(bool IsConstexpr) {
+ CompoundLiteralExprBits.IsConstexpr = IsConstexpr;
}
- bool hasStaticStorage() const { return isFileScope() && isGLValue(); }
APValue &getOrCreateStaticValue(ASTContext &Ctx) const;
APValue &getStaticValue() const;
diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h
index 69db8252f931e..791def70e72fd 100644
--- a/clang/include/clang/AST/Stmt.h
+++ b/clang/include/clang/AST/Stmt.h
@@ -668,6 +668,22 @@ class alignas(void *) Stmt {
SourceLocation OpLoc;
};
+ class CompoundLiteralExprBitfields {
+ friend class CompoundLiteralExpr;
+
+ LLVM_PREFERRED_TYPE(ExprBitfields)
+ unsigned : NumExprBits;
+
+ LLVM_PREFERRED_TYPE(StorageClass)
+ unsigned SClass : 3;
+
+ LLVM_PREFERRED_TYPE(ThreadStorageClassSpecifier)
+ unsigned TSCSpec : 2;
+
+ LLVM_PREFERRED_TYPE(bool)
+ unsigned IsConstexpr : 1;
+ };
+
class InitListExprBitfields {
friend class ASTStmtReader;
friend class InitListExpr;
@@ -1363,6 +1379,7 @@ class alignas(void *) Stmt {
MemberExprBitfields MemberExprBits;
CastExprBitfields CastExprBits;
BinaryOperatorBitfields BinaryOperatorBits;
+ CompoundLiteralExprBitfields CompoundLiteralExprBits;
InitListExprBitfields InitListExprBits;
ParenListExprBitfields ParenListExprBits;
GenericSelectionExprBitfields GenericSelectionExprBits;
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 2672bfb2952c8..17ba28c5c094c 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -185,6 +185,10 @@ def warn_c11_compat_keyword : Warning<
def warn_c23_compat_keyword : Warning<
"'%0' is incompatible with C standards before C23">,
InGroup<CPre23Compat>, DefaultIgnore;
+def warn_c23_compat_compound_literal_storage_class : Warning<
+ "compound literal storage-class specifiers are incompatible with C "
+ "standards before C23">,
+ InGroup<CPre23Compat>, DefaultIgnore;
def warn_c2y_compat_keyword : Warning<
"'%0' is incompatible with C standards before C2y">,
InGroup<CPre2yCompat>, DefaultIgnore;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index cce6f70a58893..85528249c4be4 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2471,7 +2471,8 @@ def err_init_conversion_failed : Error<
"base class|a constructor delegation|a vector element|a matrix element|a "
"block element|a block element|a complex element|a lambda capture|a compound"
" literal initializer|a related result|a parameter of CF audited function|a "
- "structured binding|a member subobject}0 "
+ "structured binding|a member subobject|a constexpr compound literal "
+ "initializer}0 "
"%diff{of type $ with an %select{rvalue|lvalue}2 of type $|"
"with an %select{rvalue|lvalue}2 of incompatible type}1,3"
"%select{|: different classes%diff{ ($ vs $)|}5,6"
@@ -3177,6 +3178,15 @@ def err_c23_constexpr_init_type_mismatch : Error<
"constexpr initializer for type %0 is of type %1">;
def err_c23_constexpr_pointer_not_null : Error<
"constexpr pointer initializer is not null">;
+def err_register_compound_literal_file_scope : Error<
+ "file-scope compound literal specifies 'register'">;
+def err_thread_local_compound_literal_without_static : Error<
+ "compound literal with 'thread_local' storage duration at block scope must "
+ "also specify 'static'">;
+def err_constexpr_compound_literal_invalid_type : Error<
+ "constexpr compound literal cannot have type %0">;
+def err_compound_literal_initializer_not_constant : Error<
+ "initializer of compound literal must be a constant expression">;
// C++ Concepts
def err_concept_decls_may_only_appear_in_global_namespace_scope : Error<
@@ -3761,6 +3771,9 @@ def err_aix_attr_unsupported : Error<"%0 attribute is not yet supported on AIX">
def err_tls_var_aligned_over_maximum : Error<
"alignment (%0) of thread-local variable %1 is greater than the maximum supported "
"alignment (%2) for a thread-local variable on this target">;
+def err_tls_compound_literal_aligned_over_maximum : Error<
+ "alignment (%0) of thread-local compound literal is greater than the maximum "
+ "supported alignment (%1) for thread-local storage on this target">;
def err_only_annotate_after_access_spec : Error<
"access specifier can only have annotation attributes">;
@@ -7950,7 +7963,8 @@ def err_typecheck_sclass_func : Error<"illegal storage class on function">;
def err_static_block_func : Error<
"function declared in block scope cannot have 'static' storage class">;
def err_typecheck_address_of : Error<"address of %select{bit-field"
- "|vector element|property expression|register variable|matrix element}0 requested">;
+ "|vector element|property expression|register variable|matrix element"
+ "|register compound literal}0 requested">;
def ext_typecheck_addrof_void : Extension<
"ISO C forbids taking the address of an expression of type 'void'">;
def err_unqualified_pointer_member_function : Error<
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 163aa483a84e3..43c88344fbb2e 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -4294,7 +4294,8 @@ class Parser : public CodeCompletionHandler {
/// \endverbatim
ExprResult ParseCompoundLiteralExpression(ParsedType Ty,
SourceLocation LParenLoc,
- SourceLocation RParenLoc);
+ SourceLocation RParenLoc,
+ const DeclSpec *DS = nullptr);
/// ParseGenericSelectionExpression - Parse a C11 generic-selection
/// [C11 6.5.1.1].
@@ -5091,6 +5092,9 @@ class Parser : public CodeCompletionHandler {
return isTypeIdInParens(isAmbiguous);
}
+ bool isCompoundLiteralStorageClassSpecifier(const Token &Tok) const;
+ void ParseCompoundLiteralStorageClassSpecifiers(DeclSpec &DS);
+
/// Finish parsing a C++ unqualified-id that is a template-id of
/// some form.
///
diff --git a/clang/include/clang/Sema/DelayedDiagnostic.h b/clang/include/clang/Sema/DelayedDiagnostic.h
index 0105089a393f1..914fb2d6bc370 100644
--- a/clang/include/clang/Sema/DelayedDiagnostic.h
+++ b/clang/include/clang/Sema/DelayedDiagnostic.h
@@ -125,7 +125,12 @@ class AccessedEntity {
/// the complete parsing of the current declaration.
class DelayedDiagnostic {
public:
- enum DDKind : unsigned char { Availability, Access, ForbiddenType };
+ enum DDKind : unsigned char {
+ Availability,
+ Access,
+ ForbiddenType,
+ ForbiddenStatic
+ };
DDKind Kind;
bool Triggered;
@@ -167,6 +172,14 @@ class DelayedDiagnostic {
return DD;
}
+ static DelayedDiagnostic makeForbiddenStatic(SourceLocation Loc) {
+ DelayedDiagnostic DD;
+ DD.Kind = ForbiddenStatic;
+ DD.Triggered = false;
+ DD.Loc = Loc;
+ return DD;
+ }
+
AccessedEntity &getAccessData() {
assert(Kind == Access && "Not an access diagnostic.");
return *reinterpret_cast<AccessedEntity*>(AccessData);
diff --git a/clang/include/clang/Sema/Initialization.h b/clang/include/clang/Sema/Initialization.h
index 2c2df1f03747b..b338151cded83 100644
--- a/clang/include/clang/Sema/Initialization.h
+++ b/clang/include/clang/Sema/Initialization.h
@@ -131,6 +131,9 @@ class alignas(8) InitializedEntity {
/// object initialized via parenthesized aggregate initialization.
EK_ParenAggInitMember,
+ /// The entity initialized by a constexpr compound literal.
+ EK_ConstexprCompoundLiteralInit,
+
// Note: err_init_conversion_failed in DiagnosticSemaKinds.td uses this
// enum as an index for its first %select. When modifying this list,
// that diagnostic text needs to be updated as well.
@@ -216,8 +219,8 @@ class alignas(8) InitializedEntity {
/// integer indicating whether the parameter is "consumed".
llvm::PointerIntPair<ParmVarDecl *, 1> Parameter;
- /// When Kind == EK_Temporary or EK_CompoundLiteralInit, the type
- /// source information for the temporary.
+ /// When Kind is EK_Temporary, EK_CompoundLiteralInit, or
+ /// EK_ConstexprCompoundLiteralInit, the type source information.
TypeSourceInfo *TypeInfo;
struct LN LocAndNRVO;
@@ -465,13 +468,21 @@ class alignas(8) InitializedEntity {
}
/// Create the entity for a compound literal initializer.
- static InitializedEntity InitializeCompoundLiteralInit(TypeSourceInfo *TSI) {
- InitializedEntity Result(EK_CompoundLiteralInit, SourceLocation(),
- TSI->getType());
+ static InitializedEntity
+ InitializeCompoundLiteralInit(TypeSourceInfo *TSI, QualType Type,
+ ConstexprSpecKind ConstexprKind) {
+ InitializedEntity Result(ConstexprKind == ConstexprSpecKind::Constexpr
+ ? EK_ConstexprCompoundLiteralInit
+ : EK_CompoundLiteralInit,
+ SourceLocation(), Type);
Result.TypeInfo = TSI;
return Result;
}
+ bool isConstexprCompoundLiteral() const {
+ return Kind == EK_ConstexprCompoundLiteralInit;
+ }
+
/// Determine the kind of initialization.
EntityKind getKind() const { return Kind; }
@@ -486,7 +497,8 @@ class alignas(8) InitializedEntity {
/// Retrieve complete type-source information for the object being
/// constructed, if known.
TypeSourceInfo *getTypeSourceInfo() const {
- if (Kind == EK_Temporary || Kind == EK_CompoundLiteralInit)
+ if (Kind == EK_Temporary || Kind == EK_CompoundLiteralInit ||
+ Kind == EK_ConstexprCompoundLiteralInit)
return TypeInfo;
return nullptr;
diff --git a/clang/include/clang/Sema/Scope.h b/clang/include/clang/Sema/Scope.h
index 58ca2c0738f3c..4f69a18fb72a5 100644
--- a/clang/include/clang/Sema/Scope.h
+++ b/clang/include/clang/Sema/Scope.h
@@ -632,8 +632,10 @@ class Scope {
/// loops where the condition follows the loop body.
void LeaveLoopBody();
- /// containedInPrototypeScope - Return true if this or a parent scope
- /// is a FunctionPrototypeScope.
+ /// Return the innermost function prototype scope containing this scope.
+ const Scope *getEnclosingFunctionPrototypeScope() const;
+
+ /// Return true if this or a parent scope is a function prototype scope.
bool containedInPrototypeScope() const;
void PushUsingDirective(UsingDirectiveDecl *UDir) {
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index d46edeb0d2872..45955c40756be 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -4051,6 +4051,8 @@ class Sema final : public SemaBase {
/// Returns true if the variable declaration is a redeclaration.
bool CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous);
void CheckVariableDeclarationType(VarDecl *NewVD);
+ bool CheckConstexprType(SourceLocation Loc, QualType T, unsigned DiagID);
+ void DiagnoseStaticInInline(SourceLocation Loc, const FunctionDecl *FD);
void CheckCompleteVariableDeclaration(VarDecl *VD);
NamedDecl *ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
@@ -7595,13 +7597,23 @@ class Sema final : public SemaBase {
/// the ParenListExpr into a sequence of comma binary operators.
ExprResult MaybeConvertParenListExprToParenExpr(Scope *S, Expr *ME);
- ExprResult ActOnCompoundLiteral(SourceLocation LParenLoc, ParsedType Ty,
- SourceLocation RParenLoc, Expr *InitExpr);
+private:
+ ExprResult BuildCompoundLiteralExpr(
+ SourceLocation LParenLoc, TypeSourceInfo *TInfo, SourceLocation RParenLoc,
+ Expr *LiteralExpr, StorageClass SC, SourceLocation StorageClassLoc,
+ ThreadStorageClassSpecifier TSC, SourceLocation ThreadStorageClassLoc,
+ ConstexprSpecKind ConstexprKind, SourceLocation ConstexprLoc);
- ExprResult BuildCompoundLiteralExpr(SourceLocation LParenLoc,
- TypeSourceInfo *TInfo,
- SourceLocation RParenLoc,
- Expr *LiteralExpr);
+public:
+ ExprResult ActOnCompoundLiteral(SourceLocation LParenLoc, ParsedType Ty,
+ SourceLocation RParenLoc, Expr *InitExpr,
+ const DeclSpec *DS = nullptr);
+
+ ExprResult BuildCompoundLiteralExpr(
+ SourceLocation LParenLoc, TypeSourceInfo *TInfo, SourceLocation RParenLoc,
+ Expr *LiteralExpr, StorageClass SC = SC_None,
+ ThreadStorageClassSpecifier TSC = TSCS_unspecified,
+ ConstexprSpecKind ConstexprKind = ConstexprSpecKind::Unspecified);
ExprResult ActOnInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList,
SourceLocation RBraceLoc);
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 3ad71a223903c..97261a632390b 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -8100,8 +8100,10 @@ ExpectedStmt ASTNodeImporter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
return std::move(Err);
return new (Importer.getToContext()) CompoundLiteralExpr(
- ToLParenLoc, ToTypeSourceInfo, ToType, E->getValueKind(),
- ToInitializer, E->isFileScope());
+ ToLParenLoc, ToTypeSourceInfo, ToType, E->getValueKind(), ToInitializer,
+ E->isFileScope(), E->getStorageClass(), E->getTSCSpec(),
+ E->isConstexpr() ? ConstexprSpecKind::Constexpr
+ : ConstexprSpecKind::Unspecified);
}
ExpectedStmt ASTNodeImporter::VisitAtomicExpr(AtomicExpr *E) {
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 9a9a76e265f6a..de6aaf503f767 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -3416,8 +3416,13 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef,
// This handles gcc's extension that allows global initializers like
// "struct x {int x;} x = (struct x) {};".
// FIXME: This accepts other cases it shouldn't!
- const Expr *Exp = cast<CompoundLiteralExpr>(this)->getInitializer();
- return Exp->isConstantInitializer(Ctx, false, Culprit);
+ const auto *CLE = cast<CompoundLiteralExpr>(this);
+ if (CLE->hasThreadStorage()) {
+ if (Culprit)
+ *Culprit = this;
+ return false;
+ }
+ return CLE->getInitializer()->isConstantInitializer(Ctx, false, Culprit);
}
case DesignatedInitUpdateExprClass: {
const DesignatedInitUpdateExpr *DIUE = cast<DesignatedInitUpdateExpr>(this);
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index a3385d3b7318f..c5d31c96c980f 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -157,6 +157,7 @@ namespace {
case ConstantExprKind::Normal:
case ConstantExprKind::ClassTemplateArgument:
case ConstantExprKind::ImmediateInvocation:
+ case ConstantExprKind::CompoundLiteralInitializer:
// Note that non-type template arguments of class type are emitted as
// template parameter objects.
return false;
@@ -171,6 +172,7 @@ namespace {
switch (Kind) {
case ConstantExprKind::Normal:
case ConstantExprKind::ImmediateInvocation:
+ case ConstantExprKind::CompoundLiteralInitializer:
return false;
case ConstantExprKind::ClassTemplateArgument:
@@ -813,6 +815,8 @@ namespace {
/// not supported by the interpreter, an error is triggered.
bool EnableNewConstInterp;
+ ConstantExprKind ConstantKind;
+
/// BottomFrame - The frame in which evaluation started. This must be
/// initialized after CurrentCall and CallStackDepth.
CallStackFrame BottomFrame;
@@ -913,11 +917,13 @@ namespace {
/// initialization.
uint64_t ArrayInitIndex = -1;
- EvalInfo(const ASTContext &C, Expr::EvalStatus &S, EvaluationMode Mode)
+ EvalInfo(const ASTContext &C, Expr::EvalStatus &S, EvaluationMode Mode,
+ ConstantExprKind Kind = ConstantExprKind::Normal)
: State(const_cast<ASTContext &>(C), S), CurrentCall(nullptr),
CallStackDepth(0), NextCallIndex(1),
StepsLeft(C.getLangOpts().ConstexprStepLimit),
EnableNewConstInterp(C.getLangOpts().EnableNewConstInterp),
+ ConstantKind(Kind),
BottomFrame(*this, SourceLocation(), /*Callee=*/nullptr,
/*This=*/nullptr,
/*CallExpr=*/nullptr, CallRef()),
@@ -1980,7 +1986,7 @@ static bool IsGlobalLValue(APValue::LValueBase B) {
return false;
case Expr::CompoundLiteralExprClass: {
const CompoundLiteralExpr *CLE = cast<CompoundLiteralExpr>(E);
- return CLE->isFileScope() && CLE->isLValue();
+ return CLE->hasStaticStorage() && CLE->isLValue();
}
case Expr::MaterializeTemporaryExprClass:
// A materialized temporary might have been lifetime-extended to static
@@ -4653,6 +4659,11 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
}
bool IsAccess = isAnyAccess(AK);
+ bool IsConstexprInitializer =
+ Info.ConstantKind == ConstantExprKind::CompoundLiteralInitializer;
+ if (const auto *VD = dyn_cast_if_present<VarDecl>(
+ Info.EvaluatingDecl.dyn_cast<const ValueDecl *>()))
+ IsConstexprInitializer |= VD->isConstexpr();
// C++11 DR1311: An lvalue-to-rvalue conversion on a volatile-qualified type
// is not a constant expression (even if the object is non-volatile). We also
@@ -4731,11 +4742,6 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
}
bool IsConstant = BaseType.isConstant(Info.Ctx);
- bool ConstexprVar = false;
- if (const auto *VD = dyn_cast_if_present<VarDecl>(
- Info.EvaluatingDecl.dyn_cast<const ValueDecl *>()))
- ConstexprVar = VD->isConstexpr();
-
// Unless we're looking at a local variable or argument in a constexpr call,
// the variable we're reading must be const (unless we are binding to a
// reference).
@@ -4755,7 +4761,7 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
return CompleteObject();
} else if (VD->isConstexpr()) {
// OK, we can read this variable.
- } else if (Info.getLangOpts().C23 && ConstexprVar) {
+ } else if (Info.getLangOpts().C23 && IsConstexprInitializer) {
Info.FFDiag(E);
return CompleteObject();
} else if (BaseType->isIntegralOrEnumerationType()) {
@@ -4879,6 +4885,14 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
assert(BaseVal && "got reference to unevaluated temporary");
} else if (const CompoundLiteralExpr *CLE =
dyn_cast_or_null<CompoundLiteralExpr>(Base)) {
+ if (CLE->hasThreadStorage()) {
+ if (IsAccess) {
+ Info.FFDiag(E);
+ return CompleteObject();
+ }
+ return CompleteObject(LVal.getLValueBase(), nullptr, BaseType);
+ }
+
// According to GCC info page:
//
// 6.28 Compound Literals
@@ -9754,6 +9768,11 @@ bool
LValueExprEvaluator::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) {
assert((!Info.getLangOpts().CPlusPlus || E->isFileScope()) &&
"lvalue compound literal in c++?");
+ if (E->hasThreadStorage()) {
+ Info.FFDiag(E);
+ return false;
+ }
+
APValue *Lit;
// If CompountLiteral has static storage, its value can be used outside
// this expression. So evaluate it once and store it in ASTContext.
@@ -21977,13 +21996,14 @@ bool Expr::EvaluateAsConstantExpr(EvalResult &Result, const ASTContext &Ctx,
assert(!isValueDependent() &&
"Expression evaluator can't be called on a dependent expression.");
bool IsConst;
- if (FastEvaluateAsRValue(this, Result.Val, Ctx, IsConst) &&
+ if (Kind != ConstantExprKind::CompoundLiteralInitializer &&
+ FastEvaluateAsRValue(this, Result.Val, Ctx, IsConst) &&
Result.Val.hasValue())
return true;
ExprTimeTraceScope TimeScope(this, Ctx, "EvaluateAsConstantExpr");
EvaluationMode EM = EvaluationMode::ConstantExpression;
- EvalInfo Info(Ctx, Result, EM);
+ EvalInfo Info(Ctx, Result, EM, Kind);
Info.InConstantContext = true;
if (Info.EnableNewConstInterp) {
@@ -22278,6 +22298,27 @@ static ICEDiag CheckEvalInICE(const Expr* E, const ASTContext &Ctx) {
return NoDiag();
}
+static const Expr *getMemberAccess(const Expr *E) {
+ E = E->IgnoreParenImpCasts();
+ while (const auto *ME = dyn_cast<MemberExpr>(E)) {
+ if (ME->isArrow())
+ return nullptr;
+ E = ME->getBase()->IgnoreParenImpCasts();
+ }
+ return E;
+}
+
+static bool isConstexprNamedConstant(const Expr *E) {
+ const auto *DRE = dyn_cast_or_null<DeclRefExpr>(getMemberAccess(E));
+ const auto *VD = DRE ? dyn_cast<VarDecl>(DRE->getDecl()) : nullptr;
+ return VD && VD->isConstexpr();
+}
+
+static bool isCompoundLiteralConstant(const Expr *E) {
+ const auto *CLE = dyn_cast_or_null<CompoundLiteralExpr>(getMemberAccess(E));
+ return CLE && CLE->isConstexpr();
+}
+
static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
assert(!E->isValueDependent() && "Should not see value dependent exprs!");
if (!E->getType()->isIntegralOrEnumerationType())
@@ -22288,6 +22329,13 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
#define STMT(Node, Base) case Expr::Node##Class:
#define EXPR(Node, Base)
#include "clang/AST/StmtNodes.inc"
+ case Expr::CompoundLiteralExprClass: {
+ const CompoundLiteralExpr *CLE = cast<CompoundLiteralExpr>(E);
+ if (CLE->isConstexpr())
+ return CheckEvalInICE(E, Ctx);
+ return ICEDiag(IK_NotICE, E->getBeginLoc());
+ }
+
case Expr::PredefinedExprClass:
case Expr::FloatingLiteralClass:
case Expr::ImaginaryLiteralClass:
@@ -22299,7 +22347,6 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
case Expr::OMPArrayShapingExprClass:
case Expr::OMPIteratorExprClass:
case Expr::CompoundAssignOperatorClass:
- case Expr::CompoundLiteralExprClass:
case Expr::ExtVectorElementExprClass:
case Expr::MatrixElementExprClass:
case Expr::DesignatedInitExprClass:
@@ -22377,20 +22424,9 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
return ICEDiag(IK_NotICE, E->getBeginLoc());
case Expr::MemberExprClass: {
- if (Ctx.getLangOpts().C23) {
- const Expr *ME = E->IgnoreParenImpCasts();
- while (const auto *M = dyn_cast<MemberExpr>(ME)) {
- if (M->isArrow())
- return ICEDiag(IK_NotICE, E->getBeginLoc());
- ME = M->getBase()->IgnoreParenImpCasts();
- }
- const auto *DRE = dyn_cast<DeclRefExpr>(ME);
- if (DRE) {
- if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
- VD && VD->isConstexpr())
- return CheckEvalInICE(E, Ctx);
- }
- }
+ if (Ctx.getLangOpts().C23 &&
+ (isConstexprNamedConstant(E) || isCompoundLiteralConstant(E)))
+ return CheckEvalInICE(E, Ctx);
return ICEDiag(IK_NotICE, E->getBeginLoc());
}
@@ -22629,8 +22665,8 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
case Expr::ObjCBridgedCastExprClass: {
const Expr *SubExpr = cast<CastExpr>(E)->getSubExpr();
if (isa<ExplicitCastExpr>(E)) {
- if (const FloatingLiteral *FL
- = dyn_cast<FloatingLiteral>(SubExpr->IgnoreParenImpCasts())) {
+ const Expr *Sub = SubExpr->IgnoreParenImpCasts();
+ if (const FloatingLiteral *FL = dyn_cast<FloatingLiteral>(Sub)) {
unsigned DestWidth = Ctx.getIntWidth(E->getType());
bool DestSigned = E->getType()->isSignedIntegerOrEnumerationType();
APSInt IgnoredVal(DestWidth, !DestSigned);
@@ -22644,6 +22680,9 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
return ICEDiag(IK_NotICE, E->getBeginLoc());
return NoDiag();
}
+ if (Ctx.getLangOpts().C23 && Sub->getType()->isArithmeticType() &&
+ (isConstexprNamedConstant(Sub) || isCompoundLiteralConstant(Sub)))
+ return CheckEvalInICE(E, Ctx);
}
switch (cast<CastExpr>(E)->getCastKind()) {
case CK_LValueToRValue:
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index 877191d456b35..5bc65c6a76cf2 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -1909,7 +1909,29 @@ void StmtPrinter::VisitCStyleCastExpr(CStyleCastExpr *Node) {
void StmtPrinter::VisitCompoundLiteralExpr(CompoundLiteralExpr *Node) {
OS << '(';
- Node->getType().print(OS, Policy);
+ if (Node->getStorageClass() == SC_Static)
+ OS << "static ";
+ else if (Node->getStorageClass() == SC_Register)
+ OS << "register ";
+ switch (Node->getTSCSpec()) {
+ case TSCS_thread_local:
+ OS << "thread_local ";
+ break;
+ case TSCS__Thread_local:
+ OS << "_Thread_local ";
+ break;
+ case TSCS___thread:
+ OS << "__thread ";
+ break;
+ case TSCS_unspecified:
+ break;
+ }
+ QualType T = Node->getType();
+ if (Node->isConstexpr()) {
+ T = Node->getTypeSourceInfo()->getType();
+ OS << "constexpr ";
+ }
+ T.print(OS, Policy);
OS << ')';
PrintExpr(Node->getInitializer());
}
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index 00c132f1ed9e0..ef617ddfd49fb 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -1600,6 +1600,9 @@ void StmtProfiler::VisitMemberExpr(const MemberExpr *S) {
void StmtProfiler::VisitCompoundLiteralExpr(const CompoundLiteralExpr *S) {
VisitExpr(S);
ID.AddBoolean(S->isFileScope());
+ ID.AddInteger(S->getStorageClass());
+ ID.AddInteger(S->getTSCSpec());
+ ID.AddBoolean(S->isConstexpr());
}
void StmtProfiler::VisitCastExpr(const CastExpr *S) {
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 9201e40bc13a1..fadf00a606f3e 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -5993,8 +5993,17 @@ CodeGenFunction::EmitLValueForFieldInitialization(LValue Base,
}
LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr *E){
- if (E->isFileScope()) {
+ if (E->isFileScope() || E->hasGlobalStorage()) {
+ if (E->getType()->isVariablyModifiedType())
+ EmitVariablyModifiedType(E->getType());
+
ConstantAddress GlobalPtr = CGM.GetAddrOfConstantCompoundLiteral(E);
+ if (E->hasThreadStorage()) {
+ llvm::Value *V = Builder.CreateThreadLocalAddress(GlobalPtr.getPointer());
+ return MakeAddrLValue(
+ Address(V, ConvertTypeForMem(E->getType()), GlobalPtr.getAlignment()),
+ E->getType(), AlignmentSource::Decl);
+ }
return MakeAddrLValue(GlobalPtr, E->getType(), AlignmentSource::Decl);
}
if (E->getType()->isVariablyModifiedType())
@@ -6005,8 +6014,10 @@ LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr *E){
const Expr *InitExpr = E->getInitializer();
LValue Result = MakeAddrLValue(DeclPtr, E->getType(), AlignmentSource::Decl);
- EmitAnyExprToMem(InitExpr, DeclPtr, E->getType().getQualifiers(),
- /*Init*/ true);
+ if (E->getType()->isAtomicType())
+ EmitAtomicInit(const_cast<Expr *>(InitExpr), Result);
+ else
+ EmitInitializationToLValue(InitExpr, Result);
// Block-scope compound literals are destroyed at the end of the enclosing
// scope in C.
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index bc35ffdaad2bd..c1309c456d4e3 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -789,9 +789,10 @@ void AggExprEmitter::VisitOpaqueValueExpr(OpaqueValueExpr *e) {
}
void AggExprEmitter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
- if (Dest.isPotentiallyAliased()) {
- // Just emit a load of the lvalue + a copy, because our compound literal
- // might alias the destination.
+ if (E->hasGlobalStorage() || E->getType()->isAtomicType() ||
+ (E->getStorageClass() == SC_Register &&
+ E->getType().isVolatileQualified()) ||
+ Dest.isPotentiallyAliased()) {
EmitAggLoadOfLValue(E);
return;
}
diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp
index 257de0145855b..2123eab890779 100644
--- a/clang/lib/CodeGen/CGExprConstant.cpp
+++ b/clang/lib/CodeGen/CGExprConstant.cpp
@@ -1089,8 +1089,8 @@ tryEmitGlobalCompoundLiteral(ConstantEmitter &emitter,
llvm::Constant *C = emitter.tryEmitForInitializer(E->getInitializer(),
addressSpace, E->getType());
if (!C) {
- assert(!E->isFileScope() &&
- "file-scope compound literal did not have constant initializer!");
+ assert(!E->isFileScope() && !E->hasGlobalStorage() &&
+ "global compound literal did not have constant initializer!");
return ConstantAddress::invalid();
}
@@ -1098,7 +1098,8 @@ tryEmitGlobalCompoundLiteral(ConstantEmitter &emitter,
CGM.getModule(), C->getType(),
E->getType().isConstantStorage(CGM.getContext(), true, false),
llvm::GlobalValue::InternalLinkage, C, ".compoundliteral", nullptr,
- llvm::GlobalVariable::NotThreadLocal,
+ E->hasThreadStorage() ? CGM.GetDefaultLLVMTLSModel()
+ : llvm::GlobalVariable::NotThreadLocal,
CGM.getContext().getTargetAddressSpace(addressSpace));
emitter.finalize(GV);
GV->setAlignment(Align.getAsAlign());
@@ -2770,7 +2771,8 @@ void CodeGenModule::setAddrOfConstantCompoundLiteral(
ConstantAddress
CodeGenModule::GetAddrOfConstantCompoundLiteral(const CompoundLiteralExpr *E) {
- assert(E->isFileScope() && "not a file-scope compound literal expr");
+ assert((E->isFileScope() || E->hasGlobalStorage()) &&
+ "not a global compound literal expression");
ConstantEmitter emitter(*this);
return tryEmitGlobalCompoundLiteral(emitter, E);
}
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 119aebb673789..861dfa1f9f1c7 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -1360,8 +1360,10 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
else
Ty = VD->getType();
- if (Ty->isVariablyModifiedType())
+ if (Ty->isVariablyModifiedType()) {
+ RunCleanupsScope Scope(*this);
EmitVariablyModifiedType(Ty);
+ }
}
}
// Emit a location at the end of the prologue.
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 6ca036664094e..55e1d489efb39 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -2656,6 +2656,59 @@ bool Parser::tryParseOpenMPArrayShapingCastPart() {
return !ErrorFound;
}
+bool Parser::isCompoundLiteralStorageClassSpecifier(const Token &Tok) const {
+ if (!getLangOpts().C23)
+ return false;
+ switch (Tok.getKind()) {
+ case tok::kw_constexpr:
+ case tok::kw_register:
+ case tok::kw_static:
+ case tok::kw_thread_local:
+ case tok::kw__Thread_local:
+ return true;
+ default:
+ return false;
+ }
+}
+
+void Parser::ParseCompoundLiteralStorageClassSpecifiers(DeclSpec &DS) {
+ DS.SetRangeStart(Tok.getLocation());
+ const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy();
+ while (isCompoundLiteralStorageClassSpecifier(Tok)) {
+ SourceLocation Loc = Tok.getLocation();
+ const char *PrevSpec = nullptr;
+ unsigned DiagID = 0;
+ bool IsInvalid = false;
+ switch (Tok.getKind()) {
+ case tok::kw_static:
+ IsInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_static, Loc,
+ PrevSpec, DiagID, Policy);
+ break;
+ case tok::kw_register:
+ IsInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_register, Loc,
+ PrevSpec, DiagID, Policy);
+ break;
+ case tok::kw_thread_local:
+ case tok::kw__Thread_local:
+ IsInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS__Thread_local,
+ Loc, PrevSpec, DiagID);
+ break;
+ case tok::kw_constexpr:
+ IsInvalid = DS.SetConstexprSpec(ConstexprSpecKind::Constexpr, Loc,
+ PrevSpec, DiagID);
+ break;
+ default:
+ llvm_unreachable("unexpected compound literal storage class specifier");
+ }
+
+ if (IsInvalid)
+ Diag(Loc, DiagID) << PrevSpec;
+
+ DS.SetRangeEnd(Loc);
+ ConsumeToken();
+ }
+}
+
ExprResult
Parser::ParseParenExpression(ParenParseOption &ExprType, bool StopIfCastExpr,
ParenExprKind ParenBehavior,
@@ -2671,7 +2724,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool StopIfCastExpr,
PreferredType.enterParenExpr(Tok.getLocation(), OpenLoc);
ExprResult Result(true);
- bool isAmbiguousTypeId;
+ bool isAmbiguousTypeId = false;
CastTy = nullptr;
if (Tok.is(tok::code_completion)) {
@@ -2773,7 +2826,8 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool StopIfCastExpr,
BridgeKeywordLoc, Ty.get(),
RParenLoc, SubExpr.get());
} else if (ExprType >= ParenParseOption::CompoundLiteral &&
- isTypeIdInParens(isAmbiguousTypeId)) {
+ (isCompoundLiteralStorageClassSpecifier(Tok) ||
+ isTypeIdInParens(isAmbiguousTypeId))) {
// Otherwise, this is a compound literal expression or cast expression.
@@ -2789,7 +2843,12 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool StopIfCastExpr,
return res;
}
- // Parse the type declarator.
+ DeclSpec CompoundDS(AttrFactory);
+ if (isCompoundLiteralStorageClassSpecifier(Tok)) {
+ ParseCompoundLiteralStorageClassSpecifiers(CompoundDS);
+ CompoundDS.Finish(Actions, Actions.getASTContext().getPrintingPolicy());
+ }
+
DeclSpec DS(AttrFactory);
ParseSpecifierQualifierList(DS);
Declarator DeclaratorInfo(DS, ParsedAttributesView::none(),
@@ -2817,12 +2876,32 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool StopIfCastExpr,
RParenLoc = T.getCloseLocation();
if (ParenBehavior == ParenExprKind::Unknown && Tok.is(tok::l_brace)) {
ExprType = ParenParseOption::CompoundLiteral;
+
+ if (CompoundDS.getBeginLoc().isValid())
+ Diag(CompoundDS.getBeginLoc(),
+ diag::warn_c23_compat_compound_literal_storage_class);
+
TypeResult Ty;
{
InMessageExpressionRAIIObject InMessage(*this, false);
Ty = Actions.ActOnTypeName(DeclaratorInfo);
}
- return ParseCompoundLiteralExpression(Ty.get(), OpenLoc, RParenLoc);
+ return ParseCompoundLiteralExpression(Ty.get(), OpenLoc, RParenLoc,
+ &CompoundDS);
+ }
+
+ if (!DeclaratorInfo.isInvalidType()) {
+ if (CompoundDS.getParsedSpecifiers() &
+ DeclSpec::PQ_StorageClassSpecifier) {
+ SourceLocation Loc = CompoundDS.getStorageClassSpecLoc();
+ if (Loc.isInvalid())
+ Loc = CompoundDS.getThreadStorageClassSpecLoc();
+ Diag(Loc, diag::err_typename_invalid_storageclass);
+ }
+ if (CompoundDS.hasConstexprSpecifier())
+ Diag(CompoundDS.getConstexprSpecLoc(),
+ diag::err_typename_invalid_constexpr)
+ << static_cast<int>(CompoundDS.getConstexprSpecifier());
}
if (ParenBehavior == ParenExprKind::Unknown && Tok.is(tok::l_paren)) {
@@ -2996,17 +3075,18 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool StopIfCastExpr,
return Result;
}
-ExprResult
-Parser::ParseCompoundLiteralExpression(ParsedType Ty,
- SourceLocation LParenLoc,
- SourceLocation RParenLoc) {
+ExprResult Parser::ParseCompoundLiteralExpression(ParsedType Ty,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc,
+ const DeclSpec *DS) {
assert(Tok.is(tok::l_brace) && "Not a compound literal!");
if (!getLangOpts().C99) // Compound literals don't exist in C90.
Diag(LParenLoc, diag::ext_c99_compound_literal);
PreferredType.enterTypeCast(Tok.getLocation(), Ty.get());
ExprResult Result = ParseInitializer();
if (!Result.isInvalid() && Ty)
- return Actions.ActOnCompoundLiteral(LParenLoc, Ty, RParenLoc, Result.get());
+ return Actions.ActOnCompoundLiteral(LParenLoc, Ty, RParenLoc, Result.get(),
+ DS);
return Result;
}
diff --git a/clang/lib/Sema/CheckExprLifetime.cpp b/clang/lib/Sema/CheckExprLifetime.cpp
index fafee76ec18c3..e5cfc3086fb58 100644
--- a/clang/lib/Sema/CheckExprLifetime.cpp
+++ b/clang/lib/Sema/CheckExprLifetime.cpp
@@ -131,6 +131,7 @@ getEntityLifetime(const InitializedEntity *Entity,
case InitializedEntity::EK_Temporary:
case InitializedEntity::EK_CompoundLiteralInit:
+ case InitializedEntity::EK_ConstexprCompoundLiteralInit:
case InitializedEntity::EK_RelatedResult:
// We don't yet know the storage duration of the surrounding temporary.
// Assume it's got full-expression duration for now, it will patch up our
@@ -658,7 +659,7 @@ static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path,
case Stmt::CompoundLiteralExprClass: {
if (auto *CLE = dyn_cast<CompoundLiteralExpr>(Init)) {
- if (!CLE->isFileScope())
+ if (!CLE->isFileScope() && !CLE->hasGlobalStorage())
Visit(Path, Local(CLE), RK);
}
break;
diff --git a/clang/lib/Sema/DelayedDiagnostic.cpp b/clang/lib/Sema/DelayedDiagnostic.cpp
index cb2721b92090e..4f94da0e64fba 100644
--- a/clang/lib/Sema/DelayedDiagnostic.cpp
+++ b/clang/lib/Sema/DelayedDiagnostic.cpp
@@ -68,6 +68,7 @@ void DelayedDiagnostic::Destroy() {
break;
case ForbiddenType:
+ case ForbiddenStatic:
break;
}
}
diff --git a/clang/lib/Sema/Scope.cpp b/clang/lib/Sema/Scope.cpp
index fc79b1a056ed9..1cd7a21893ba4 100644
--- a/clang/lib/Sema/Scope.cpp
+++ b/clang/lib/Sema/Scope.cpp
@@ -103,14 +103,15 @@ void Scope::Init(Scope *parent, unsigned flags) {
NRVO = std::nullopt;
}
-bool Scope::containedInPrototypeScope() const {
- const Scope *S = this;
- while (S) {
+const Scope *Scope::getEnclosingFunctionPrototypeScope() const {
+ for (const Scope *S = this; S; S = S->getParent())
if (S->isFunctionPrototypeScope())
- return true;
- S = S->getParent();
- }
- return false;
+ return S;
+ return nullptr;
+}
+
+bool Scope::containedInPrototypeScope() const {
+ return getEnclosingFunctionPrototypeScope() != nullptr;
}
void Scope::EnterLoopBody(LabelDecl *LD) {
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index a553c6994f0ed..cf09bf2615b07 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -7419,7 +7419,7 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl,
/// Given that we are within the definition of the given function,
/// will that definition behave like C99's 'inline', where the
/// definition is discarded except for optimization purposes?
-static bool isFunctionDefinitionDiscarded(Sema &S, FunctionDecl *FD) {
+static bool isFunctionDefinitionDiscarded(Sema &S, const FunctionDecl *FD) {
// Try to avoid calling GetGVALinkageForFunction.
// All cases of this require the 'inline' keyword.
@@ -7433,6 +7433,14 @@ static bool isFunctionDefinitionDiscarded(Sema &S, FunctionDecl *FD) {
return S.Context.GetGVALinkageForFunction(FD) == GVA_AvailableExternally;
}
+void Sema::DiagnoseStaticInInline(SourceLocation Loc, const FunctionDecl *FD) {
+ if (!FD || !isFunctionDefinitionDiscarded(*this, FD))
+ return;
+
+ Diag(Loc, diag::warn_static_local_in_extern_inline);
+ MaybeSuggestAddingStaticToDecl(FD);
+}
+
/// Determine whether a variable is extern "C" prior to attaching
/// an initializer. We can't just call isExternC() here, because that
/// will also compute and cache whether the declaration is externally
@@ -8190,14 +8198,9 @@ NamedDecl *Sema::ActOnVariableDeclarator(
// be marked 'static'. Also note that it's possible to get these
// semantics in C++ using __attribute__((gnu_inline)).
if (SC == SC_Static && S->getFnParent() != nullptr &&
- !NewVD->getType().isConstQualified()) {
- FunctionDecl *CurFD = getCurFunctionDecl();
- if (CurFD && isFunctionDefinitionDiscarded(*this, CurFD)) {
- Diag(D.getDeclSpec().getStorageClassSpecLoc(),
- diag::warn_static_local_in_extern_inline);
- MaybeSuggestAddingStaticToDecl(CurFD);
- }
- }
+ !NewVD->getType().isConstQualified())
+ DiagnoseStaticInInline(D.getDeclSpec().getStorageClassSpecLoc(),
+ getCurFunctionDecl());
if (D.getDeclSpec().isModulePrivateSpecified()) {
if (IsVariableTemplateSpecialization)
@@ -8898,32 +8901,31 @@ static bool checkForConflictWithNonVisibleExternC(Sema &S, const T *ND,
return false;
}
-static bool CheckC23ConstexprVarType(Sema &SemaRef, SourceLocation VarLoc,
- QualType T) {
- QualType CanonT = SemaRef.Context.getCanonicalType(T);
+bool Sema::CheckConstexprType(SourceLocation Loc, QualType T, unsigned DiagID) {
+ QualType CanonT = Context.getCanonicalType(T);
// C23 6.7.1p5: An object declared with storage-class specifier constexpr or
// any of its members, even recursively, shall not have an atomic type, or a
// variably modified type, or a type that is volatile or restrict qualified.
if (CanonT->isVariablyModifiedType()) {
- SemaRef.Diag(VarLoc, diag::err_c23_constexpr_invalid_type) << T;
+ Diag(Loc, DiagID) << T;
return true;
}
// Arrays are qualified by their element type, so get the base type (this
// works on non-arrays as well).
- CanonT = SemaRef.Context.getBaseElementType(CanonT);
+ CanonT = Context.getBaseElementType(CanonT);
if (CanonT->isAtomicType() || CanonT.isVolatileQualified() ||
CanonT.isRestrictQualified()) {
- SemaRef.Diag(VarLoc, diag::err_c23_constexpr_invalid_type) << T;
+ Diag(Loc, DiagID) << T;
return true;
}
if (CanonT->isRecordType()) {
const RecordDecl *RD = CanonT->getAsRecordDecl();
if (!RD->isInvalidDecl() &&
- llvm::any_of(RD->fields(), [&SemaRef, VarLoc](const FieldDecl *F) {
- return CheckC23ConstexprVarType(SemaRef, VarLoc, F->getType());
+ llvm::any_of(RD->fields(), [this, Loc, DiagID](const FieldDecl *F) {
+ return CheckConstexprType(Loc, F->getType(), DiagID);
}))
return true;
}
@@ -9199,7 +9201,8 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
}
if (getLangOpts().C23 && NewVD->isConstexpr() &&
- CheckC23ConstexprVarType(*this, NewVD->getLocation(), T)) {
+ CheckConstexprType(NewVD->getLocation(), T,
+ diag::err_c23_constexpr_invalid_type)) {
NewVD->setInvalidDecl();
return;
}
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 1b272b5416860..cf6ce9b5508be 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -9017,6 +9017,14 @@ void Sema::PopParsingDeclaration(ParsingDeclState state, Decl *decl) {
case DelayedDiagnostic::ForbiddenType:
handleDelayedForbiddenType(*this, diag, decl);
break;
+
+ case DelayedDiagnostic::ForbiddenStatic:
+ if (const FunctionDecl *FD = decl->getAsFunction();
+ FD && FD->isThisDeclarationADefinition()) {
+ diag.Triggered = true;
+ DiagnoseStaticInInline(diag.Loc, FD);
+ }
+ break;
}
}
} while ((pool = pool->getParent()));
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index ed3d27b5adc27..b5f19964cbefd 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -63,6 +63,7 @@
#include "clang/Sema/SemaOpenMP.h"
#include "clang/Sema/SemaPseudoObject.h"
#include "clang/Sema/Template.h"
+#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/ConvertUTF.h"
@@ -123,6 +124,40 @@ static void DiagnoseUnusedOfDecl(Sema &S, NamedDecl *D, SourceLocation Loc) {
}
}
+static bool checkThreadLocalCompoundLiteral(Sema &S, SourceLocation Loc,
+ QualType T) {
+ if (S.getLangOpts().ObjCAutoRefCount && T->isObjCLifetimeType()) {
+ Qualifiers::ObjCLifetime Lifetime = T.getObjCLifetime();
+ if (Lifetime == Qualifiers::OCL_None)
+ Lifetime = T->getObjCARCImplicitLifetime();
+
+ if (Lifetime && Lifetime != Qualifiers::OCL_ExplicitNone) {
+ S.Diag(Loc, diag::err_arc_thread_ownership)
+ << S.Context.getLifetimeQualifiedType(T, Lifetime);
+ return true;
+ }
+ }
+
+ if (T.isDestructedType()) {
+ S.Diag(Loc, diag::err_thread_nontrivial_dtor);
+ return true;
+ }
+
+ unsigned MaxAlign = S.Context.getTargetInfo().getMaxTLSAlign();
+ if (!MaxAlign || T->isDependentType())
+ return false;
+
+ CharUnits MaxAlignChars = S.Context.toCharUnitsFromBits(MaxAlign);
+ CharUnits TypeAlign = S.Context.getTypeAlignInChars(T);
+ if (TypeAlign <= MaxAlignChars)
+ return false;
+
+ S.Diag(Loc, diag::err_tls_compound_literal_aligned_over_maximum)
+ << (unsigned)TypeAlign.getQuantity()
+ << (unsigned)MaxAlignChars.getQuantity();
+ return true;
+}
+
void Sema::NoteDeletedFunction(FunctionDecl *Decl) {
assert(Decl && Decl->isDeleted());
@@ -519,6 +554,54 @@ SourceRange Sema::getExprRange(Expr *E) const {
// Standard Promotions and Conversions
//===----------------------------------------------------------------------===//
+namespace {
+enum {
+ AO_Bit_Field = 0,
+ AO_Vector_Element = 1,
+ AO_Property_Expansion = 2,
+ AO_Register_Variable = 3,
+ AO_Matrix_Element = 4,
+ AO_Register_Compound_Literal = 5,
+ AO_No_Error = 6
+};
+}
+
+using PrimaryObject = llvm::PointerUnion<ValueDecl *, CompoundLiteralExpr *>;
+
+static PrimaryObject getPrimaryObject(Expr *E) {
+ E = E->IgnoreParens();
+ switch (E->getStmtClass()) {
+ case Stmt::DeclRefExprClass:
+ return cast<DeclRefExpr>(E)->getDecl();
+ case Stmt::CompoundLiteralExprClass:
+ return cast<CompoundLiteralExpr>(E);
+ case Stmt::MemberExprClass:
+ if (cast<MemberExpr>(E)->isArrow())
+ return {};
+ return getPrimaryObject(cast<MemberExpr>(E)->getBase());
+ case Stmt::ArraySubscriptExprClass: {
+ Expr *Base = cast<ArraySubscriptExpr>(E)->getBase()->IgnoreParens();
+ if (auto *ICE = dyn_cast<ImplicitCastExpr>(Base);
+ ICE && ICE->getSubExpr()->getType()->isArrayType())
+ return getPrimaryObject(ICE->getSubExpr());
+ return {};
+ }
+ case Stmt::UnaryOperatorClass: {
+ UnaryOperator *UO = cast<UnaryOperator>(E);
+ if (UO->getOpcode() == UO_Real || UO->getOpcode() == UO_Imag ||
+ UO->getOpcode() == UO_Extension)
+ return getPrimaryObject(UO->getSubExpr());
+ return {};
+ }
+ case Stmt::ImplicitCastExprClass:
+ return getPrimaryObject(cast<ImplicitCastExpr>(E)->getSubExpr());
+ case Stmt::CXXUuidofExprClass:
+ return cast<CXXUuidofExpr>(E)->getGuidDecl();
+ default:
+ return {};
+ }
+}
+
/// DefaultFunctionArrayConversion (C99 6.3.2.1p3, C99 6.3.2.1p4).
ExprResult Sema::DefaultFunctionArrayConversion(Expr *E, bool Diagnose) {
// Handle any placeholder expressions which made it here.
@@ -552,6 +635,13 @@ ExprResult Sema::DefaultFunctionArrayConversion(Expr *E, bool Diagnose) {
// T" can be converted to an rvalue of type "pointer to T".
//
if (getLangOpts().C99 || getLangOpts().CPlusPlus || E->isLValue()) {
+ if (!getLangOpts().CPlusPlus) {
+ auto *CLE = getPrimaryObject(E).dyn_cast<CompoundLiteralExpr *>();
+ if (CLE && CLE->getStorageClass() == SC_Register)
+ return Diag(E->getExprLoc(), diag::err_typecheck_address_of)
+ << AO_Register_Compound_Literal << CLE->getSourceRange();
+ }
+
ExprResult Res = ImpCastExprToType(E, Context.getArrayDecayedType(Ty),
CK_ArrayToPointerDecay);
if (Res.isInvalid())
@@ -7425,9 +7515,9 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
return CheckForImmediateInvocation(MaybeBindToTemporary(TheCall), FDecl);
}
-ExprResult
-Sema::ActOnCompoundLiteral(SourceLocation LParenLoc, ParsedType Ty,
- SourceLocation RParenLoc, Expr *InitExpr) {
+ExprResult Sema::ActOnCompoundLiteral(SourceLocation LParenLoc, ParsedType Ty,
+ SourceLocation RParenLoc, Expr *InitExpr,
+ const DeclSpec *DS) {
assert(Ty && "ActOnCompoundLiteral(): missing type");
assert(InitExpr && "ActOnCompoundLiteral(): missing expression");
@@ -7436,13 +7526,90 @@ Sema::ActOnCompoundLiteral(SourceLocation LParenLoc, ParsedType Ty,
if (!TInfo)
TInfo = Context.getTrivialTypeSourceInfo(literalType);
- return BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc, InitExpr);
-}
-
-ExprResult
-Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
- SourceLocation RParenLoc, Expr *LiteralExpr) {
+ StorageClass SC = SC_None;
+ ThreadStorageClassSpecifier TSC = TSCS_unspecified;
+ ConstexprSpecKind ConstexprKind = ConstexprSpecKind::Unspecified;
+ SourceLocation StorageClassLoc;
+ SourceLocation ThreadStorageClassLoc;
+ SourceLocation ConstexprLoc;
+ if (DS) {
+ if (DS->getStorageClassSpec() == DeclSpec::SCS_static)
+ SC = SC_Static;
+ else if (DS->getStorageClassSpec() == DeclSpec::SCS_register)
+ SC = SC_Register;
+
+ TSC = DS->getThreadStorageClassSpec();
+ ConstexprKind = DS->getConstexprSpecifier();
+ StorageClassLoc = DS->getStorageClassSpecLoc();
+ ThreadStorageClassLoc = DS->getThreadStorageClassSpecLoc();
+ ConstexprLoc = DS->getConstexprSpecLoc();
+ }
+
+ return BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc, InitExpr, SC,
+ StorageClassLoc, TSC, ThreadStorageClassLoc,
+ ConstexprKind, ConstexprLoc);
+}
+
+ExprResult Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc,
+ TypeSourceInfo *TInfo,
+ SourceLocation RParenLoc,
+ Expr *LiteralExpr, StorageClass SC,
+ ThreadStorageClassSpecifier TSC,
+ ConstexprSpecKind ConstexprKind) {
+ return BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc, LiteralExpr, SC,
+ LParenLoc, TSC, LParenLoc, ConstexprKind,
+ LParenLoc);
+}
+
+ExprResult Sema::BuildCompoundLiteralExpr(
+ SourceLocation LParenLoc, TypeSourceInfo *TInfo, SourceLocation RParenLoc,
+ Expr *LiteralExpr, StorageClass SC, SourceLocation StorageClassLoc,
+ ThreadStorageClassSpecifier TSC, SourceLocation ThreadStorageClassLoc,
+ ConstexprSpecKind ConstexprKind, SourceLocation ConstexprLoc) {
QualType literalType = TInfo->getType();
+ const Scope *S = getCurScope();
+ const Scope *PrototypeScope = S->getEnclosingFunctionPrototypeScope();
+
+ bool HasStatic = SC == SC_Static;
+ bool HasRegister = SC == SC_Register;
+ bool HasThreadStorage = TSC != TSCS_unspecified;
+ bool HasConstexpr = ConstexprKind == ConstexprSpecKind::Constexpr;
+
+ bool IsPrototypeScope = PrototypeScope;
+ bool IsFunctionDeclarationScope =
+ PrototypeScope && PrototypeScope->isFunctionDeclarationScope();
+ bool IsFileScope = !CurContext->isFunctionOrMethod() &&
+ !S->isInCFunctionScope() && !PrototypeScope;
+
+ if (HasConstexpr && literalType->isObjectType())
+ literalType.addConst();
+
+ if (getLangOpts().C23 &&
+ (SC != SC_None || HasThreadStorage || HasConstexpr)) {
+ if (HasRegister && IsFileScope) {
+ Diag(StorageClassLoc, diag::err_register_compound_literal_file_scope);
+ return ExprError();
+ }
+ if (HasThreadStorage && !IsFileScope && !HasStatic) {
+ Diag(ThreadStorageClassLoc,
+ diag::err_thread_local_compound_literal_without_static);
+ return ExprError();
+ }
+ if (HasThreadStorage && !Context.getTargetInfo().isTLSSupported()) {
+ Diag(ThreadStorageClassLoc, diag::err_thread_unsupported);
+ return ExprError();
+ }
+ if (HasConstexpr &&
+ CheckConstexprType(ConstexprLoc, literalType,
+ diag::err_constexpr_compound_literal_invalid_type))
+ return ExprError();
+ }
+
+ if (getLangOpts().C23 && IsFileScope &&
+ literalType->isVariablyModifiedType()) {
+ Diag(LParenLoc, diag::err_vm_decl_in_file_scope);
+ return ExprError();
+ }
if (literalType->isArrayType()) {
if (RequireCompleteSizedType(
@@ -7477,32 +7644,47 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
return ExprError();
}
} else if (!literalType->isDependentType() &&
- RequireCompleteType(LParenLoc, literalType,
- diag::err_typecheck_decl_incomplete_type,
- SourceRange(LParenLoc, LiteralExpr->getSourceRange().getEnd())))
+ RequireCompleteType(
+ LParenLoc, literalType,
+ diag::err_typecheck_decl_incomplete_type,
+ SourceRange(LParenLoc,
+ LiteralExpr->getSourceRange().getEnd())))
return ExprError();
- InitializedEntity Entity
- = InitializedEntity::InitializeCompoundLiteralInit(TInfo);
- InitializationKind Kind
- = InitializationKind::CreateCStyleCast(LParenLoc,
- SourceRange(LParenLoc, RParenLoc),
- /*InitList=*/true);
+ InitializedEntity Entity = InitializedEntity::InitializeCompoundLiteralInit(
+ TInfo, literalType, ConstexprKind);
+ InitializationKind Kind = InitializationKind::CreateCStyleCast(
+ LParenLoc, SourceRange(LParenLoc, RParenLoc),
+ /*InitList=*/true);
InitializationSequence InitSeq(*this, Entity, Kind, LiteralExpr);
- ExprResult Result = InitSeq.Perform(*this, Entity, Kind, LiteralExpr,
- &literalType);
+ ExprResult Result =
+ InitSeq.Perform(*this, Entity, Kind, LiteralExpr, &literalType);
if (Result.isInvalid())
return ExprError();
LiteralExpr = Result.get();
- // We treat the compound literal as being at file scope if it's not in a
- // function or method body, or within the function's prototype scope. This
- // means the following compound literal is not at file scope:
- // void func(char *para[(int [1]){ 0 }[0]);
- const Scope *S = getCurScope();
- bool IsFileScope = !CurContext->isFunctionOrMethod() &&
- !S->isInCFunctionScope() &&
- (!S || !S->isFunctionPrototypeScope());
+ if (HasConstexpr && !LiteralExpr->isTypeDependent() &&
+ !LiteralExpr->isValueDependent() && !literalType->isDependentType()) {
+ SmallVector<PartialDiagnosticAt, 4> Notes;
+ Expr::EvalResult Eval;
+ Eval.Diag = &Notes;
+ if (!LiteralExpr->EvaluateAsConstantExpr(
+ Eval, Context,
+ Expr::ConstantExprKind::CompoundLiteralInitializer) ||
+ Notes.size() > 0) {
+ SourceLocation DiagLoc = ConstexprLoc;
+ if (Notes.size() == 1 && Notes.front().second.getDiagID() ==
+ diag::note_invalid_subexpr_in_const_expr) {
+ DiagLoc = Notes.front().first;
+ Notes.clear();
+ }
+ Diag(DiagLoc, diag::err_compound_literal_initializer_not_constant)
+ << LiteralExpr->getSourceRange();
+ for (const PartialDiagnosticAt &Note : Notes)
+ Diag(Note.first, Note.second);
+ return ExprError();
+ }
+ }
// In C, compound literals are l-values for some reason.
// For GCC compatibility, in C++, file-scope array compound literals with
@@ -7527,33 +7709,52 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
? VK_PRValue
: VK_LValue;
+ bool HasGlobalStorage =
+ IsFileScope || (getLangOpts().C23 && (HasStatic || HasThreadStorage));
+
+ if (HasThreadStorage && checkThreadLocalCompoundLiteral(
+ *this, ThreadStorageClassLoc, literalType))
+ return ExprError();
+
// C99 6.5.2.5
// "If the compound literal occurs outside the body of a function, the
// initializer list shall consist of constant expressions."
- if (IsFileScope)
+ if (HasGlobalStorage || HasConstexpr)
if (auto ILE = dyn_cast<InitListExpr>(LiteralExpr))
for (unsigned i = 0, j = ILE->getNumInits(); i != j; i++) {
Expr *Init = ILE->getInit(i);
- if (!Init->isTypeDependent() && !Init->isValueDependent() &&
+ if (!HasConstexpr && !Init->isTypeDependent() &&
+ !Init->isValueDependent() &&
!Init->isConstantInitializer(Context)) {
Diag(Init->getExprLoc(), diag::err_init_element_not_constant)
<< Init->getSourceBitField();
return ExprError();
}
- ILE->setInit(i, ConstantExpr::Create(Context, Init));
+ Expr::EvalResult Eval;
+ if (HasConstexpr &&
+ Init->EvaluateAsRValue(Eval, Context,
+ /*InConstantContext=*/true) &&
+ Eval.Val.hasValue())
+ ILE->setInit(i, ConstantExpr::Create(Context, Init, Eval.Val));
+ else
+ ILE->setInit(i, ConstantExpr::Create(Context, Init));
}
- auto *E = new (Context) CompoundLiteralExpr(LParenLoc, TInfo, literalType, VK,
- LiteralExpr, IsFileScope);
- if (IsFileScope) {
- if (!LiteralExpr->isTypeDependent() &&
- !LiteralExpr->isValueDependent() &&
- !literalType->isDependentType()) // C99 6.5.2.5p3
+ auto *E = new (Context)
+ CompoundLiteralExpr(LParenLoc, TInfo, literalType, VK, LiteralExpr,
+ IsFileScope, SC, TSC, ConstexprKind);
+
+ if (HasGlobalStorage && !HasConstexpr) {
+ if (!LiteralExpr->isTypeDependent() && !LiteralExpr->isValueDependent() &&
+ !literalType->isDependentType()) { // C99 6.5.2.5p3
if (CheckForConstantInitializer(LiteralExpr))
return ExprError();
- } else if (literalType.getAddressSpace() != LangAS::opencl_private &&
- literalType.getAddressSpace() != LangAS::Default) {
+ }
+ }
+
+ if (!IsFileScope && literalType.getAddressSpace() != LangAS::opencl_private &&
+ literalType.getAddressSpace() != LangAS::Default) {
// Embedded-C extensions to C99 6.5.2.5:
// "If the compound literal occurs inside the body of a function, the
// type name shall not be qualified by an address-space qualifier."
@@ -7562,7 +7763,17 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
return ExprError();
}
- if (!IsFileScope && !getLangOpts().CPlusPlus) {
+ if (HasStatic && !literalType.isConstQualified()) {
+ if (!IsPrototypeScope) {
+ DiagnoseStaticInInline(StorageClassLoc, getCurFunctionDecl());
+ } else if (IsFunctionDeclarationScope &&
+ DelayedDiagnostics.shouldDelayDiagnostics()) {
+ DelayedDiagnostics.add(
+ sema::DelayedDiagnostic::makeForbiddenStatic(StorageClassLoc));
+ }
+ }
+
+ if (!HasGlobalStorage && !IsPrototypeScope && !getLangOpts().CPlusPlus) {
// Compound literals that have automatic storage duration are destroyed at
// the end of the scope in C; in C++, they're just temporaries.
@@ -14843,78 +15054,6 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op,
}
}
-/// getPrimaryDecl - Helper function for CheckAddressOfOperand().
-/// This routine allows us to typecheck complex/recursive expressions
-/// where the declaration is needed for type checking. We only need to
-/// handle cases when the expression references a function designator
-/// or is an lvalue. Here are some examples:
-/// - &(x) => x
-/// - &*****f => f for f a function designator.
-/// - &s.xx => s
-/// - &s.zz[1].yy -> s, if zz is an array
-/// - *(x + 1) -> x, if x is an array
-/// - &"123"[2] -> 0
-/// - & __real__ x -> x
-///
-/// FIXME: We don't recurse to the RHS of a comma, nor handle pointers to
-/// members.
-static ValueDecl *getPrimaryDecl(Expr *E) {
- switch (E->getStmtClass()) {
- case Stmt::DeclRefExprClass:
- return cast<DeclRefExpr>(E)->getDecl();
- case Stmt::MemberExprClass:
- // If this is an arrow operator, the address is an offset from
- // the base's value, so the object the base refers to is
- // irrelevant.
- if (cast<MemberExpr>(E)->isArrow())
- return nullptr;
- // Otherwise, the expression refers to a part of the base
- return getPrimaryDecl(cast<MemberExpr>(E)->getBase());
- case Stmt::ArraySubscriptExprClass: {
- // FIXME: This code shouldn't be necessary! We should catch the implicit
- // promotion of register arrays earlier.
- Expr* Base = cast<ArraySubscriptExpr>(E)->getBase();
- if (ImplicitCastExpr* ICE = dyn_cast<ImplicitCastExpr>(Base)) {
- if (ICE->getSubExpr()->getType()->isArrayType())
- return getPrimaryDecl(ICE->getSubExpr());
- }
- return nullptr;
- }
- case Stmt::UnaryOperatorClass: {
- UnaryOperator *UO = cast<UnaryOperator>(E);
-
- switch(UO->getOpcode()) {
- case UO_Real:
- case UO_Imag:
- case UO_Extension:
- return getPrimaryDecl(UO->getSubExpr());
- default:
- return nullptr;
- }
- }
- case Stmt::ParenExprClass:
- return getPrimaryDecl(cast<ParenExpr>(E)->getSubExpr());
- case Stmt::ImplicitCastExprClass:
- // If the result of an implicit cast is an l-value, we care about
- // the sub-expression; otherwise, the result here doesn't matter.
- return getPrimaryDecl(cast<ImplicitCastExpr>(E)->getSubExpr());
- case Stmt::CXXUuidofExprClass:
- return cast<CXXUuidofExpr>(E)->getGuidDecl();
- default:
- return nullptr;
- }
-}
-
-namespace {
-enum {
- AO_Bit_Field = 0,
- AO_Vector_Element = 1,
- AO_Property_Expansion = 2,
- AO_Register_Variable = 3,
- AO_Matrix_Element = 4,
- AO_No_Error = 5
-};
-}
/// Diagnose invalid operand for address of operations.
///
/// \param Type The type of operand which cannot have its address taken.
@@ -15018,7 +15157,8 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
// Technically, there should be a check for array subscript
// expressions here, but the result of one is always an lvalue anyway.
}
- ValueDecl *dcl = getPrimaryDecl(op);
+ PrimaryObject Primary = getPrimaryObject(op);
+ ValueDecl *dcl = Primary.dyn_cast<ValueDecl *>();
if (auto *FD = dyn_cast_or_null<FunctionDecl>(dcl))
if (!checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true,
@@ -15169,6 +15309,10 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
NonTypeTemplateParmDecl, BindingDecl, MSGuidDecl,
UnnamedGlobalConstantDecl>(dcl))
llvm_unreachable("Unknown/unexpected decl type");
+ } else if (!getLangOpts().CPlusPlus) {
+ if (auto *CLE = Primary.dyn_cast<CompoundLiteralExpr *>();
+ CLE && CLE->getStorageClass() == SC_Register)
+ AddressOfError = AO_Register_Compound_Literal;
}
if (AddressOfError != AO_No_Error) {
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 09d9f1eabd058..7f0a691a1cb28 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -194,18 +194,15 @@ static void updateGNUCompoundLiteralRValue(Expr *E) {
}
}
-static bool initializingConstexprVariable(const InitializedEntity &Entity) {
- Decl *D = Entity.getDecl();
- const InitializedEntity *Parent = &Entity;
-
- while (Parent) {
- D = Parent->getDecl();
- Parent = Parent->getParent();
+static bool initializingConstexprObject(const InitializedEntity &Entity) {
+ for (const InitializedEntity *Parent = &Entity; Parent;
+ Parent = Parent->getParent()) {
+ if (Parent->isConstexprCompoundLiteral())
+ return true;
+ if (const auto *VD = dyn_cast_if_present<VarDecl>(Parent->getDecl());
+ VD && VD->isConstexpr())
+ return true;
}
-
- if (const auto *VD = dyn_cast_if_present<VarDecl>(D); VD && VD->isConstexpr())
- return true;
-
return false;
}
@@ -1311,6 +1308,7 @@ static void warnBracedScalarInit(Sema &S, const InitializedEntity &Entity,
case InitializedEntity::EK_New:
case InitializedEntity::EK_Temporary:
case InitializedEntity::EK_CompoundLiteralInit:
+ case InitializedEntity::EK_ConstexprCompoundLiteralInit:
// No warning, braces are part of the syntax of the underlying construct.
break;
@@ -1436,7 +1434,8 @@ void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity,
// parts.
CheckComplexType(Entity, IList, DeclType, Index,
StructuredList, StructuredIndex);
- } else if (DeclType->isScalarType()) {
+ } else if (DeclType->isScalarType() ||
+ (!SemaRef.getLangOpts().CPlusPlus && DeclType->isAtomicType())) {
CheckScalarType(Entity, IList, DeclType, Index,
StructuredList, StructuredIndex);
} else if (DeclType->isVectorType()) {
@@ -1626,7 +1625,7 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
if (!VerifyOnly)
CheckStringInit(expr, ElemType, arrayType, SemaRef, Entity,
SemaRef.getLangOpts().C23 &&
- initializingConstexprVariable(Entity));
+ initializingConstexprObject(Entity));
if (StructuredList)
UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
++Index;
@@ -2177,7 +2176,7 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
if (!VerifyOnly)
CheckStringInit(
IList->getInit(Index), DeclType, arrayType, SemaRef, Entity,
- SemaRef.getLangOpts().C23 && initializingConstexprVariable(Entity));
+ SemaRef.getLangOpts().C23 && initializingConstexprObject(Entity));
if (StructuredList) {
UpdateStructuredListElement(StructuredList, StructuredIndex,
IList->getInit(Index));
@@ -3809,6 +3808,7 @@ DeclarationName InitializedEntity::getName() const {
case EK_BlockElement:
case EK_LambdaToBlockConversionBlockElement:
case EK_CompoundLiteralInit:
+ case EK_ConstexprCompoundLiteralInit:
case EK_RelatedResult:
return DeclarationName();
}
@@ -3844,6 +3844,7 @@ ValueDecl *InitializedEntity::getDecl() const {
case EK_LambdaToBlockConversionBlockElement:
case EK_LambdaCapture:
case EK_CompoundLiteralInit:
+ case EK_ConstexprCompoundLiteralInit:
case EK_RelatedResult:
return nullptr;
}
@@ -3868,6 +3869,7 @@ bool InitializedEntity::allowsNRVO() const {
case EK_New:
case EK_Temporary:
case EK_CompoundLiteralInit:
+ case EK_ConstexprCompoundLiteralInit:
case EK_Base:
case EK_Delegating:
case EK_ArrayElement:
@@ -3907,6 +3909,9 @@ unsigned InitializedEntity::dumpImpl(raw_ostream &OS) const {
case EK_New: OS << "New"; break;
case EK_Temporary: OS << "Temporary"; break;
case EK_CompoundLiteralInit: OS << "CompoundLiteral";break;
+ case EK_ConstexprCompoundLiteralInit:
+ OS << "ConstexprCompoundLiteral";
+ break;
case EK_RelatedResult: OS << "RelatedResult"; break;
case EK_Base: OS << "Base"; break;
case EK_Delegating: OS << "Delegating"; break;
@@ -4930,7 +4935,8 @@ static void TryReferenceListInitialization(Sema &S,
return;
}
// Can't reference initialize a compound literal.
- if (Entity.getKind() == InitializedEntity::EK_CompoundLiteralInit) {
+ if (Entity.getKind() == InitializedEntity::EK_CompoundLiteralInit ||
+ Entity.getKind() == InitializedEntity::EK_ConstexprCompoundLiteralInit) {
Sequence.SetFailed(InitializationSequence::FK_ReferenceBindingToInitList);
return;
}
@@ -7196,6 +7202,7 @@ static AssignmentAction getAssignmentAction(const InitializedEntity &Entity,
case InitializedEntity::EK_LambdaToBlockConversionBlockElement:
case InitializedEntity::EK_LambdaCapture:
case InitializedEntity::EK_CompoundLiteralInit:
+ case InitializedEntity::EK_ConstexprCompoundLiteralInit:
return AssignmentAction::Initializing;
}
@@ -7223,6 +7230,7 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity) {
case InitializedEntity::EK_LambdaToBlockConversionBlockElement:
case InitializedEntity::EK_LambdaCapture:
case InitializedEntity::EK_CompoundLiteralInit:
+ case InitializedEntity::EK_ConstexprCompoundLiteralInit:
case InitializedEntity::EK_TemplateParameter:
return false;
@@ -7265,6 +7273,7 @@ static bool shouldDestroyEntity(const InitializedEntity &Entity) {
case InitializedEntity::EK_ArrayElement:
case InitializedEntity::EK_Exception:
case InitializedEntity::EK_CompoundLiteralInit:
+ case InitializedEntity::EK_ConstexprCompoundLiteralInit:
case InitializedEntity::EK_RelatedResult:
return true;
}
@@ -7306,6 +7315,7 @@ static SourceLocation getInitializationLoc(const InitializedEntity &Entity,
case InitializedEntity::EK_BlockElement:
case InitializedEntity::EK_LambdaToBlockConversionBlockElement:
case InitializedEntity::EK_CompoundLiteralInit:
+ case InitializedEntity::EK_ConstexprCompoundLiteralInit:
case InitializedEntity::EK_RelatedResult:
return Initializer->getBeginLoc();
}
@@ -7562,6 +7572,7 @@ static bool isExplicitTemporary(const InitializedEntity &Entity,
switch (Entity.getKind()) {
case InitializedEntity::EK_Temporary:
case InitializedEntity::EK_CompoundLiteralInit:
+ case InitializedEntity::EK_ConstexprCompoundLiteralInit:
case InitializedEntity::EK_RelatedResult:
break;
default:
@@ -8579,7 +8590,7 @@ ExprResult InitializationSequence::Perform(Sema &S,
return ExprError();
CurInit = CurInitExprRes;
- if (S.getLangOpts().C23 && initializingConstexprVariable(Entity)) {
+ if (S.getLangOpts().C23 && initializingConstexprObject(Entity)) {
CheckC23ConstexprInitConversion(S, SourceType, Entity.getType(),
CurInit.get());
@@ -8623,7 +8634,7 @@ ExprResult InitializationSequence::Perform(Sema &S,
CheckStringInit(CurInit.get(), UpdateType ? *ResultType : Ty,
S.Context.getAsArrayType(Ty), S, Entity,
S.getLangOpts().C23 &&
- initializingConstexprVariable(Entity));
+ initializingConstexprObject(Entity));
break;
}
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 0725664a4e050..239700db3d0eb 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -3103,12 +3103,13 @@ class TreeTransform {
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- ExprResult RebuildCompoundLiteralExpr(SourceLocation LParenLoc,
- TypeSourceInfo *TInfo,
- SourceLocation RParenLoc,
- Expr *Init) {
- return getSema().BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc,
- Init);
+ ExprResult RebuildCompoundLiteralExpr(
+ SourceLocation LParenLoc, TypeSourceInfo *TInfo, SourceLocation RParenLoc,
+ Expr *Init, StorageClass SC = SC_None,
+ ThreadStorageClassSpecifier TSC = TSCS_unspecified,
+ ConstexprSpecKind ConstexprKind = ConstexprSpecKind::Unspecified) {
+ return getSema().BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc, Init,
+ SC, TSC, ConstexprKind);
}
/// Build a new extended vector or matrix element access expression.
@@ -14325,7 +14326,10 @@ TreeTransform<Derived>::TransformCompoundLiteralExpr(CompoundLiteralExpr *E) {
return getDerived().RebuildCompoundLiteralExpr(
E->getLParenLoc(), NewT,
- /*FIXME:*/ E->getInitializer()->getEndLoc(), Init.get());
+ /*FIXME:*/ E->getInitializer()->getEndLoc(), Init.get(),
+ E->getStorageClass(), E->getTSCSpec(),
+ E->isConstexpr() ? ConstexprSpecKind::Constexpr
+ : ConstexprSpecKind::Unspecified);
}
template<typename Derived>
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index 97f1857e200ca..2e8c055a8ac6a 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -1239,6 +1239,9 @@ void ASTStmtReader::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
E->setTypeSourceInfo(readTypeSourceInfo());
E->setInitializer(Record.readSubExpr());
E->setFileScope(Record.readInt());
+ E->setStorageClass(static_cast<StorageClass>(Record.readInt()));
+ E->setTSCSpec(static_cast<ThreadStorageClassSpecifier>(Record.readInt()));
+ E->setConstexpr(Record.readInt());
}
void ASTStmtReader::VisitExtVectorElementExpr(ExtVectorElementExpr *E) {
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index 70477f4cf4001..f0ff9eb1ed80f 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -1206,6 +1206,9 @@ void ASTStmtWriter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
Record.AddTypeSourceInfo(E->getTypeSourceInfo());
Record.AddStmt(E->getInitializer());
Record.push_back(E->isFileScope());
+ Record.push_back(E->getStorageClass());
+ Record.push_back(E->getTSCSpec());
+ Record.push_back(E->isConstexpr());
Code = serialization::EXPR_COMPOUND_LITERAL;
}
diff --git a/clang/test/AST/c23-compound-literal-print.c b/clang/test/AST/c23-compound-literal-print.c
new file mode 100644
index 0000000000000..c8e4fb7d1e8e3
--- /dev/null
+++ b/clang/test/AST/c23-compound-literal-print.c
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -std=c23 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -std=c23 -emit-pch -o %t %s
+// RUN: %clang_cc1 -std=c23 -include-pch %t -ast-print -x c /dev/null | FileCheck %s
+
+// CHECK-LABEL: int f1(void)
+// CHECK: return (constexpr int){1} + (static _Thread_local int){2} + (register int){3} + (constexpr const int){4};
+int f1(void) {
+ return (constexpr int){1} + (_Thread_local static int){2} + (register int){3} +
+ (constexpr const int){4};
+}
+
+// CHECK-LABEL: int f2(void)
+// CHECK: return (int[3]){1, 2, 3}[0] + (constexpr int[3]){1, 2, 3}[0];
+int f2(void) {
+ return (int[3]){1, 2, 3}[0] + (constexpr int[3]){1, 2, 3}[0];
+}
+
+typedef const int T;
+
+// CHECK-LABEL: int f3(void)
+// CHECK: return (constexpr T){1} + (constexpr int[]){1}[0] + (constexpr const int[]){1}[0] + (constexpr T[]){1}[0];
+int f3(void) {
+ return (constexpr T){1} + (constexpr int[]){1}[0] +
+ (constexpr const int[]){1}[0] + (constexpr T[]){1}[0];
+}
+
+// CHECK-LABEL: void f4(void)
+// CHECK: typedef typeof (*(int (*)[(static _Thread_local int){1}])0) T1;
+// CHECK: typedef typeof (*(int (*)[(register int){1}])0) T2;
+void f4(void) {
+ typedef typeof(*(int (*)[(static thread_local int){1}])0) T1;
+ typedef typeof(*(int (*)[(register int){1}])0) T2;
+}
diff --git a/clang/test/C/drs/dr3xx.c b/clang/test/C/drs/dr3xx.c
index 0f67470b013a5..e5d85dca78122 100644
--- a/clang/test/C/drs/dr3xx.c
+++ b/clang/test/C/drs/dr3xx.c
@@ -226,6 +226,7 @@ extern int dr339_v;
void *dr339 = &(int (*)[dr339_v]){ 0 }; /* c89only-warning {{variable length arrays are a C99 feature}}
c99andup-warning {{variable length array used}}
c89only-warning {{compound literals are a C99-specific feature}}
+ c23andup-error {{variably modified type declaration not allowed at file scope}}
*/
/* WG14 DR340: yes
diff --git a/clang/test/CodeGen/c23-compound-literal.c b/clang/test/CodeGen/c23-compound-literal.c
new file mode 100644
index 0000000000000..d255e72a23d1b
--- /dev/null
+++ b/clang/test/CodeGen/c23-compound-literal.c
@@ -0,0 +1,275 @@
+// RUN: %clang_cc1 -std=c23 -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s
+
+struct S { int a; int b; };
+
+// CHECK-LABEL: define dso_local i32 @f1()
+// CHECK: %[[VALUE:.*]] = load i32, ptr @.compoundliteral, align 4
+// CHECK-NEXT: ret i32 %[[VALUE]]
+int f1(void) {
+ return (static int){42};
+}
+
+// CHECK-LABEL: define dso_local i32 @f2()
+// CHECK: %.compoundliteral = alloca i32
+// CHECK: store i32 7, ptr %.compoundliteral
+// CHECK-NEXT: %[[VALUE:.*]] = load i32, ptr %.compoundliteral, align 4
+// CHECK-NEXT: ret i32 %[[VALUE]]
+int f2(void) {
+ return (constexpr int){7};
+}
+
+// CHECK-LABEL: define dso_local ptr @f3()
+// CHECK: ret ptr @.compoundliteral.1
+const int *f3(void) {
+ return &(static constexpr int){15};
+}
+
+// CHECK-LABEL: define dso_local i32 @f4()
+// CHECK: [[ADDR:%.*]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @.compoundliteral.2)
+// CHECK-NEXT: %[[VALUE:.*]] = load i32, ptr [[ADDR]], align 4
+// CHECK-NEXT: ret i32 %[[VALUE]]
+int f4(void) {
+ return (thread_local static int){2};
+}
+
+// CHECK-LABEL: define dso_local ptr @f5()
+// CHECK: [[ADDR:%.*]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @.compoundliteral.3)
+// CHECK-NEXT: ret ptr [[ADDR]]
+int *f5(void) {
+ return &(thread_local static int){2};
+}
+
+// CHECK-LABEL: define dso_local i32 @f6()
+// CHECK: store ptr @.compoundliteral.4, ptr %a, align 8
+// CHECK-NEXT: %[[BASE:.*]] = load ptr, ptr %a, align 8
+// CHECK-NEXT: %[[MEMBER:.*]] = getelementptr inbounds nuw %struct.S, ptr %[[BASE]], i32 0, i32 0
+// CHECK-NEXT: %[[VALUE:.*]] = load i32, ptr %[[MEMBER]], align 4
+// CHECK-NEXT: ret i32 %[[VALUE]]
+int f6(void) {
+ struct S *a = &(static struct S){1, 2};
+ return a->a;
+}
+
+// CHECK-LABEL: define dso_local i64 @f7()
+// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %retval, ptr align 4 @.compoundliteral.5, i64 8, i1 true)
+// CHECK-NEXT: %[[VALUE:.*]] = load i64, ptr %retval, align 4
+// CHECK-NEXT: ret i64 %[[VALUE]]
+struct S f7(void) {
+ return (static volatile struct S){9, 10};
+}
+
+// CHECK-LABEL: define dso_local i64 @f8()
+// CHECK: [[ADDR:%.*]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @.compoundliteral.6)
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %retval, ptr align 4 [[ADDR]], i64 8, i1 true)
+// CHECK-NEXT: %[[VALUE:.*]] = load i64, ptr %retval, align 4
+// CHECK-NEXT: ret i64 %[[VALUE]]
+struct S f8(void) {
+ return (thread_local static volatile struct S){11, 12};
+}
+
+// CHECK-LABEL: define dso_local i64 @f9()
+// CHECK: %.compoundliteral = alloca %struct.S
+// CHECK: store i32 13
+// CHECK: store i32 14
+// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %retval, ptr align 4 %.compoundliteral, i64 8, i1 true)
+// CHECK-NEXT: %[[VALUE:.*]] = load i64, ptr %retval, align 4
+// CHECK-NEXT: ret i64 %[[VALUE]]
+struct S f9(void) {
+ return (register volatile struct S){13, 14};
+}
+
+// CHECK-LABEL: define dso_local i32 @f10()
+// CHECK: %.compoundliteral = alloca %struct.S
+// CHECK: store i32 3
+// CHECK: store i32 4
+// CHECK: store ptr %.compoundliteral, ptr %a, align 8
+// CHECK-NEXT: %[[BASE:.*]] = load ptr, ptr %a, align 8
+// CHECK-NEXT: %[[MEMBER:.*]] = getelementptr inbounds nuw %struct.S, ptr %[[BASE]], i32 0, i32 0
+// CHECK-NEXT: %[[VALUE:.*]] = load i32, ptr %[[MEMBER]], align 4
+// CHECK-NEXT: ret i32 %[[VALUE]]
+int f10(void) {
+ const struct S *a = &(constexpr struct S){3, 4};
+ return a->a;
+}
+
+// CHECK-LABEL: define dso_local i32 @f11()
+// CHECK: %[[VALUE:.*]] = load i32, ptr @.compoundliteral.7, align 4
+// CHECK-NEXT: ret i32 %[[VALUE]]
+int f11(void) {
+ return (static int[]){5, 6, 7}[0];
+}
+
+// CHECK-LABEL: define dso_local i32 @f12()
+// CHECK: %.compoundliteral = alloca [3 x i32]
+// CHECK: store i32 8, ptr %.compoundliteral
+// CHECK: store i32 9
+// CHECK: store i32 10
+// CHECK: %[[ELEMENT:.*]] = getelementptr inbounds [3 x i32], ptr %.compoundliteral, i64 0, i64 0
+// CHECK-NEXT: %[[VALUE:.*]] = load i32, ptr %[[ELEMENT]], align 4
+// CHECK-NEXT: ret i32 %[[VALUE]]
+int f12(void) {
+ return (constexpr int[]){8, 9, 10}[0];
+}
+
+// CHECK-LABEL: define dso_local i32 @f13()
+// CHECK: %.compoundliteral = alloca i32
+// CHECK: store i32 99, ptr %.compoundliteral
+// CHECK-NEXT: %[[VALUE:.*]] = load i32, ptr %.compoundliteral, align 4
+// CHECK-NEXT: ret i32 %[[VALUE]]
+int f13(void) {
+ return (register constexpr int){99};
+}
+
+// CHECK-LABEL: define dso_local i32 @f14()
+// CHECK: %a = alloca i32
+// CHECK: store i32 16, ptr %a
+// CHECK-NEXT: %[[VALUE:.*]] = load atomic i32, ptr %a seq_cst, align 4
+// CHECK-NEXT: ret i32 %[[VALUE]]
+int f14(void) {
+ register _Atomic int a = 16;
+ return a;
+}
+
+// CHECK-LABEL: define dso_local i32 @f15()
+// CHECK: %.compoundliteral = alloca i32
+// CHECK: store i32 16, ptr %.compoundliteral
+// CHECK-NEXT: %[[VALUE:.*]] = load atomic i32, ptr %.compoundliteral seq_cst, align 4
+// CHECK-NEXT: ret i32 %[[VALUE]]
+int f15(void) {
+ return (register _Atomic int){16};
+}
+
+// CHECK-LABEL: define dso_local i64 @f16()
+// CHECK: %a = alloca %struct.S, align 8
+// CHECK: store i32 17
+// CHECK: store i32 18
+// CHECK: %[[VALUE:.*]] = load atomic i64, ptr %a seq_cst, align 8
+// CHECK-NEXT: store i64 %[[VALUE]], ptr %retval, align 4
+// CHECK-NEXT: %[[RESULT:.*]] = load i64, ptr %retval, align 4
+// CHECK-NEXT: ret i64 %[[RESULT]]
+struct S f16(void) {
+ register _Atomic(struct S) a = {(struct S){17, 18}};
+ return a;
+}
+
+// CHECK-LABEL: define dso_local i64 @f17()
+// CHECK: %.compoundliteral = alloca %struct.S, align 8
+// CHECK: store i32 17
+// CHECK: store i32 18
+// CHECK: %[[VALUE:.*]] = load atomic i64, ptr %.compoundliteral seq_cst, align 8
+// CHECK-NEXT: store i64 %[[VALUE]], ptr %retval, align 4
+// CHECK-NEXT: %[[RESULT:.*]] = load i64, ptr %retval, align 4
+// CHECK-NEXT: ret i64 %[[RESULT]]
+struct S f17(void) {
+ return (register _Atomic(struct S)){(struct S){17, 18}};
+}
+
+// CHECK-LABEL: define dso_local i32 @f18()
+// CHECK: %.compoundliteral = alloca i32
+// CHECK: store i32 5, ptr %.compoundliteral
+// CHECK-NEXT: %[[VALUE:.*]] = load i32, ptr %.compoundliteral, align 4
+// CHECK-NEXT: ret i32 %[[VALUE]]
+int f18(void) {
+ return (int){5};
+}
+
+// CHECK-LABEL: define dso_local i32 @f19(i32 noundef %a)
+// CHECK: %[[OLD:.*]] = load i32, ptr %a.addr, align 4
+// CHECK-NEXT: %[[INC:.*]] = add nsw i32 %[[OLD]], 1
+// CHECK-NEXT: store i32 %[[INC]], ptr %a.addr, align 4
+// CHECK: load ptr, ptr @.compoundliteral.8, align 8
+// CHECK: %[[RESULT:.*]] = load i32, ptr %a.addr, align 4
+// CHECK-NEXT: ret i32 %[[RESULT]]
+int f19(int a) {
+ (void)(static int (*)[a++]){0};
+ return a;
+}
+
+// CHECK-LABEL: define dso_local i32 @f20(i32 noundef %a)
+// CHECK: %[[OLD:.*]] = load i32, ptr %a.addr, align 4
+// CHECK-NEXT: %[[INC:.*]] = add nsw i32 %[[OLD]], 1
+// CHECK-NEXT: store i32 %[[INC]], ptr %a.addr, align 4
+// CHECK: %[[ADDR:.*]] = call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @.compoundliteral.9)
+// CHECK-NEXT: load ptr, ptr %[[ADDR]], align 8
+// CHECK: %[[RESULT:.*]] = load i32, ptr %a.addr, align 4
+// CHECK-NEXT: ret i32 %[[RESULT]]
+int f20(int a) {
+ (void)(thread_local static int (*)[a++]){0};
+ return a;
+}
+
+int f21(void);
+
+// CHECK-LABEL: define dso_local i32 @f22(
+// CHECK: %.compoundliteral = alloca i32
+// CHECK: [[CALL:%call]] = call i32 @f21()
+// CHECK-NEXT: store i32 [[CALL]], ptr %.compoundliteral
+// CHECK-NEXT: %[[BOUND:.*]] = load i32, ptr %.compoundliteral, align 4
+// CHECK-NEXT: zext i32 %[[BOUND]] to i64
+// CHECK: ret i32
+// CHECK-NEXT: }
+int f22(int a[(int){f21()}]) {
+ return a[0];
+}
+
+// CHECK-LABEL: define dso_local i32 @f23(
+// CHECK: %.compoundliteral = alloca i32
+// CHECK: [[CALL:%call]] = call i32 @f21()
+// CHECK-NEXT: store i32 [[CALL]], ptr %.compoundliteral
+// CHECK-NEXT: %[[BOUND:.*]] = load i32, ptr %.compoundliteral, align 4
+// CHECK-NEXT: zext i32 %[[BOUND]] to i64
+// CHECK: ret i32
+// CHECK-NEXT: }
+int f23(int a[(register int){f21()}]) {
+ return a[0];
+}
+
+// CHECK-LABEL: define dso_local i32 @f24(
+// CHECK: %[[BOUND:.*]] = load volatile i32, ptr @.compoundliteral.10, align 4
+// CHECK-NEXT: zext i32 %[[BOUND]] to i64
+// CHECK: ret i32
+// CHECK-NEXT: }
+int f24(int a[(static volatile int){13}]) {
+ return a[0];
+}
+
+// CHECK-LABEL: define dso_local i32 @f25(
+// CHECK: [[ADDR:%.*]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @.compoundliteral.11)
+// CHECK-NEXT: %[[BOUND:.*]] = load volatile i32, ptr [[ADDR]], align 4
+// CHECK-NEXT: zext i32 %[[BOUND]] to i64
+// CHECK: ret i32
+// CHECK-NEXT: }
+int f25(int a[(static thread_local volatile int){14}]) {
+ return a[0];
+}
+
+// CHECK-LABEL: define dso_local i32 @f26(
+// CHECK-NOT: call i32 @f21()
+// CHECK-NOT: load volatile i32
+// CHECK: ret i32 0
+int f26(int b(int a[((int){f21()} + (static volatile int){15})])) {
+ return 0;
+}
+
+// CHECK-LABEL: define dso_local i32 @f27(
+// CHECK: %.compoundliteral = alloca i32
+// CHECK: [[CALL:%call]] = call i32 @f21()
+// CHECK-NEXT: store i32 [[CALL]], ptr %.compoundliteral
+// CHECK-NEXT: load i32, ptr %.compoundliteral, align 4
+// CHECK-NEXT: ret i32 0
+int f27(int (*a(void))[((void)(int){f21()}, 1)]) {
+ return 0;
+}
+
+int f28(const int *);
+
+// CHECK-LABEL: define dso_local i32 @f29(
+// CHECK: %.compoundliteral = alloca i32
+// CHECK: store i32 3, ptr %.compoundliteral
+// CHECK-NEXT: %[[CALL:.*]] = call i32 @f28(ptr noundef %.compoundliteral)
+// CHECK-NEXT: zext i32 %[[CALL]] to i64
+// CHECK: ret i32
+// CHECK-NEXT: }
+int f29(int a[f28(&(constexpr int){3})]) {
+ return a[0];
+}
diff --git a/clang/test/CodeGenObjC/c23-compound-literal.m b/clang/test/CodeGenObjC/c23-compound-literal.m
new file mode 100644
index 0000000000000..245284cb23017
--- /dev/null
+++ b/clang/test/CodeGenObjC/c23-compound-literal.m
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -std=c23 -triple x86_64-apple-macosx10.15 -emit-llvm -fobjc-arc -disable-llvm-passes -o - %s | FileCheck %s
+
+typedef struct {
+ id a;
+} S;
+int f1(const S *);
+
+// CHECK-LABEL: define i32 @f2(
+// CHECK: %.compoundliteral = alloca %struct.S, align 8
+// CHECK: store ptr null, ptr %{{.*}}, align 8
+// CHECK: %[[CALL:.*]] = call i32 @f1(ptr noundef %.compoundliteral)
+// CHECK-NEXT: zext i32 %[[CALL]] to i64
+// CHECK: %[[RESULT:.*]] = load i32, ptr %{{.*}}, align 4
+// CHECK-NEXT: call void @__destructor_8_s0(ptr %.compoundliteral)
+// CHECK-NEXT: ret i32 %[[RESULT]]
+// CHECK-NEXT: }
+int f2(int a[f1(&(constexpr S){.a = 0})]) {
+ return a[0];
+}
diff --git a/clang/test/Parser/expressions.c b/clang/test/Parser/expressions.c
index 82556c091206f..2921158dd5f35 100644
--- a/clang/test/Parser/expressions.c
+++ b/clang/test/Parser/expressions.c
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c17 -fsyntax-only -verify=expected,c17 %s
+// RUN: %clang_cc1 -std=c23 -Wpre-c23-compat -fsyntax-only -verify=expected,c23 %s
+// RUN: %clang_cc1 -std=c23 -triple x86_64-apple-darwin10 -fsyntax-only -verify=expected,notls %s
void test1(void) {
if (sizeof (int){ 1}) {} // sizeof compound literal
@@ -73,3 +75,17 @@ void test8(void) {
callee(foobar, // expected-error {{use of undeclared identifier 'foobar'}}
fizbin); // expected-error {{use of undeclared identifier 'fizbin'}}
}
+
+void test9(void) {
+ (void)(static int){1}; // c17-error {{expected expression}} \
+ // c23-warning {{compound literal storage-class specifiers are incompatible with C standards before C23}}
+
+ (void)(register int){2}; // c17-error {{expected expression}} \
+ // c23-warning {{compound literal storage-class specifiers are incompatible with C standards before C23}}
+
+ (void)(constexpr int){3}; // c17-error {{use of undeclared identifier 'constexpr'}} \
+ // c23-warning {{compound literal storage-class specifiers are incompatible with C standards before C23}}
+
+ (void)(_Thread_local static int){4}; // c17-error {{expected expression}} notls-error {{thread-local storage is not supported for the current target}} \
+ // c23-warning {{compound literal storage-class specifiers are incompatible with C standards before C23}}
+}
diff --git a/clang/test/Sema/c23-compound-literal.c b/clang/test/Sema/c23-compound-literal.c
new file mode 100644
index 0000000000000..44759108bcd3a
--- /dev/null
+++ b/clang/test/Sema/c23-compound-literal.c
@@ -0,0 +1,343 @@
+// RUN: %clang_cc1 -std=c23 -triple x86_64-unknown-linux-gnu -verify -fsyntax-only %s
+// RUN: %clang_cc1 -std=c23 -triple x86_64-scei-ps4 -verify=expected,ps4 -fsyntax-only %s
+
+#define M static
+struct S { int a; char b; };
+int f1(void);
+
+void test1(void) {
+ (void)(constexpr int){1};
+ (void)&(static int){42};
+ (void)(register int){0};
+ (void)(static thread_local int){1};
+ (void)(constexpr struct S){1, 'a'};
+ (void)(static struct S){2, 'b'};
+ (void)(register struct S){3, 'c'};
+}
+
+void test2(void) {
+ (void)(static constexpr int){1};
+ (void)(constexpr static int){2};
+ (void)(static thread_local int){3};
+ (void)(thread_local static int){4};
+ (void)(constexpr register int){5};
+ (void)(constexpr static thread_local int){6}; // expected-error {{cannot combine with previous '_Thread_local' declaration specifier}}
+}
+
+void test3(void) {
+ (void)(static static int){1}; // expected-warning {{duplicate 'static' declaration specifier}}
+ (void)(constexpr constexpr int){2}; // expected-warning {{duplicate 'constexpr' declaration specifier}}
+ (void)(register register int){3}; // expected-warning {{duplicate 'register' declaration specifier}}
+ (void)(thread_local thread_local int){4}; // expected-warning {{duplicate '_Thread_local' declaration specifier}} expected-error {{compound literal with 'thread_local' storage duration at block scope must also specify 'static'}}
+}
+
+void test4(void) {
+ (void)(register static int){1}; // expected-error {{cannot combine with previous 'register' declaration specifier}}
+ (void)(register thread_local int){2}; // expected-error {{cannot combine with previous 'register' declaration specifier}}
+ (void)(register constexpr int){3};
+ (void)(static register int){4}; // expected-error {{cannot combine with previous 'static' declaration specifier}}
+ (void)(register _Atomic int){5};
+}
+
+void test5(void) {
+ (void)&(thread_local int){1}; // expected-error {{compound literal with 'thread_local' storage duration at block scope must also specify 'static'}}
+}
+
+int *a1 = &(register int){42}; // expected-error {{file-scope compound literal specifies 'register'}}
+
+void test6(void) {
+ (void)(constexpr volatile int){1}; // expected-error {{constexpr compound literal cannot have type 'const volatile int'}}
+ (void)(constexpr _Atomic int){1}; // expected-error {{constexpr compound literal cannot have type 'const _Atomic(int)'}}
+
+ int c;
+ (void)(constexpr int[c]){0}; // expected-error {{constexpr compound literal cannot have type 'const int[c]'}}
+}
+
+void test7(void) {
+ (void)(constexpr int){f1()}; // expected-error {{initializer of compound literal must be a constant expression}}
+ (void)(static int){f1()}; // expected-error {{initializer element is not a compile-time constant}}
+ (void)(register constexpr int){f1()}; // expected-error {{initializer of compound literal must be a constant expression}}
+ (void)(constexpr int){1 / 0};
+ // expected-error at -1 {{initializer of compound literal must be a constant expression}}
+ // expected-note at -2 {{division by zero}}
+ // expected-warning at -3 {{division by zero is undefined}}
+}
+
+const int a2 = 1;
+const double a3 = 1.0;
+
+void test8(void) {
+ (void)(constexpr int){a2}; // expected-error {{initializer of compound literal must be a constant expression}}
+ (void)(constexpr double){a3}; // expected-error {{initializer of compound literal must be a constant expression}}
+
+ const int a = 2;
+ (void)(constexpr int){a}; // expected-error {{initializer of compound literal must be a constant expression}}
+
+ struct S1 {
+ int a;
+ };
+
+ (void)(constexpr int){(constexpr int){1}};
+ (void)(constexpr struct S1){.a = (constexpr int){1}};
+ (void)(constexpr int){(int){1}};
+ (void)(constexpr int){(static int){1}};
+}
+
+void test9(void) {
+ int *a = &(register int){1}; // expected-error {{address of register compound literal requested}}
+ int *b = (register int[1]){1}; // expected-error {{address of register compound literal requested}}
+ struct S2 { int a; };
+ int *c = &(register struct S2){1}.a; // expected-error {{address of register compound literal requested}}
+ double *d = &__real__ (register _Complex double){1}; // expected-error {{address of register compound literal requested}}
+ double *e = &__imag__ (register _Complex double){1}; // expected-error {{address of register compound literal requested}}
+ int *f = &_Generic(0, int: (register int){1}); // expected-error {{address of register compound literal requested}}
+ int *g = _Generic(0, int: (register int[1]){1}); // expected-error {{address of register compound literal requested}}
+ int *h = &_Generic(0, int: (register struct S2){1}).a; // expected-error {{address of register compound literal requested}}
+ int *i = &__extension__ (register int){1}; // expected-error {{address of register compound literal requested}}
+}
+
+int a5[1];
+struct S3 {
+ int *a;
+};
+struct S4 {
+ int a[1];
+};
+
+int *test10(void) {
+ return &((register struct S3){a5}.a[0]);
+}
+
+int *test11(void) {
+ return &(register struct S4){{1}}.a[0]; // expected-error {{address of register compound literal requested}}
+}
+
+enum { E1 = (constexpr int){42} };
+enum { E2 = (constexpr int){} };
+static int a6[(constexpr int){10}];
+static int a7[(constexpr int){} + 1];
+static const int *a8 = &(constexpr int){5};
+static int a9 = (constexpr int){7};
+static_assert(!(constexpr int){});
+
+struct S5 { int a; };
+enum { E3 = (constexpr struct S5){42}.a };
+enum { E4 = (int)(constexpr double){1.0} };
+
+union U1 {
+ int a;
+ long b;
+};
+enum { E5 = (constexpr union U1){.a = 9}.a };
+enum {
+ E6 = (constexpr union U1){.a = 9}.b
+ // expected-error at -1 {{expression is not an integer constant expression}}
+ // expected-note at -2 {{read of member 'b' of union with active member 'a' is not allowed in a constant expression}}
+};
+
+void test12(void) {
+ static int a = (constexpr int){8};
+ int b[(constexpr int){3}];
+ switch ((constexpr int){1}) {
+ case (constexpr int){1}:
+ break;
+ }
+}
+
+void test13(void) {
+ (constexpr int){1} = 2; // expected-error {{read-only variable is not assignable}}
+ (constexpr int[1]){1}[0] = 2; // expected-error {{read-only variable is not assignable}}
+ (constexpr struct S){1, 'a'}.a = 2; // expected-error {{read-only variable is not assignable}}
+}
+
+int *a10 = &(static int){100};
+int *a11 = &(thread_local int){200}; // expected-error {{initializer element is not a compile-time constant}}
+const int *a12 = &(constexpr int){300};
+
+void test14(void) {
+ const int *a = (constexpr int[]){1, 2, 3};
+ int *b = (static int[]){4, 5, 6};
+}
+
+int a13 = (thread_local int){1}; // expected-error {{initializer element is not a compile-time constant}}
+int a14 = (thread_local static int){1}; // expected-error {{initializer element is not a compile-time constant}}
+int a15 = 1 + (thread_local int){1}; // expected-error {{initializer element is not a compile-time constant}}
+int a16 = +(thread_local int){1}; // expected-error {{initializer element is not a compile-time constant}}
+int a17 = (thread_local struct S5){1}.a; // expected-error {{initializer element is not a compile-time constant}}
+int a18 = *(thread_local int[1]){1}; // expected-error {{initializer element is not a compile-time constant}}
+
+struct S7 {
+ unsigned char a;
+};
+
+void test15(void) {
+ static int a;
+ (void)(constexpr int *){&a}; // expected-error {{constexpr pointer initializer is not null}}
+ (void)(constexpr struct S7){-1}; // expected-error {{constexpr initializer evaluates to -1 which is not exactly representable in type 'unsigned char'}}
+}
+
+int a19[3];
+static int *a20 = a19 + (constexpr int){1};
+static int *a21 = (constexpr int){0}; // expected-warning {{expression which evaluates to zero treated as a null pointer constant of type 'int *'}}
+static int *a22 = (constexpr int *){0};
+
+struct S8 {
+ int *restrict a;
+};
+void test16(void) {
+ (void)(constexpr struct S8){0}; // expected-error {{constexpr compound literal cannot have type 'int *restrict'}}
+}
+
+void test17(void) {
+ (void)(constexpr char[]){"\xFF"};
+ (void)(constexpr unsigned char[]){"\xFF"}; // expected-error {{constexpr initializer evaluates to -1 which is not exactly representable in type 'const unsigned char'}}
+}
+
+void test18(void) {
+ static const int *a = &(constexpr int){1}; // expected-error {{initializer element is not a compile-time constant}}
+ static const int *b = &(static constexpr int){1};
+}
+
+void f2(int a[sizeof((static int){1})]);
+void f3(int a[sizeof((register int){1})]);
+void f4(int a[sizeof((constexpr int){1})]);
+void f5(int a[sizeof((thread_local static int){1})]);
+int f6(void);
+
+void f7(int a[(constexpr int){f6()}]); // expected-error {{initializer of compound literal must be a constant expression}}
+void f8(int a[(static int){f6()}]); // expected-error {{initializer element is not a compile-time constant}}
+
+typedef void F1(int a[(int){f6()}]);
+typedef void F2(int a[(thread_local int){1}]); // expected-error {{compound literal with 'thread_local' storage duration at block scope must also specify 'static'}}
+void (*a23)(int a[(register int){f6()}]);
+
+typedef int T __attribute__((address_space(1)));
+void f9(int a[sizeof((T){0})]); // expected-error {{compound literal in function scope may not be qualified with an address space}}
+int f10(int a[sizeof((T){0})]) { // expected-error {{compound literal in function scope may not be qualified with an address space}}
+ return a[0];
+}
+
+void test19(void) {
+ (static T){0}; // expected-error {{compound literal in function scope may not be qualified with an address space}}
+}
+
+int f11(
+ typeof(sizeof((register T){0})) a(void)) { // expected-error {{compound literal in function scope may not be qualified with an address space}}
+ return a();
+}
+
+inline int f12(void) { // expected-note {{use 'static' to give inline function 'f12' internal linkage}}
+ return (static int){1}; // expected-warning {{non-constant static local variable in inline function may be different in different files}}
+}
+
+inline int f13(int a[(static int){1}]) { // expected-warning {{non-constant static local variable in inline function may be different in different files}} \
+ // expected-note {{use 'static' to give inline function 'f13' internal linkage}}
+ return a[0];
+}
+
+inline int f14(int a[(static int){1}]);
+
+inline int f15(int a[(static const int){1}]) {
+ return a[0];
+}
+
+extern inline int f16(int a[(static int){1}]) {
+ return a[0];
+}
+
+static inline int f17(int a[(static int){1}]) {
+ return a[0];
+}
+
+inline int f18(int b(int a[sizeof((static int){1})])) {
+ return 0;
+}
+
+inline int f19(int (*a(void))[sizeof((static int){1})]) { // expected-warning {{non-constant static local variable in inline function may be different in different files}}
+ // expected-note at -1 {{use 'static' to give inline function 'f19' internal linkage}}
+ return 0;
+}
+
+inline typeof((static int){1}) f20(void) {
+ return 0;
+}
+typeof((register int){1}) f21(void); // expected-error {{file-scope compound literal specifies 'register'}}
+
+inline int f22(int a) __attribute__((enable_if((static int){1}, "enabled"))) { // expected-warning {{non-constant static local variable in inline function may be different in different files}} \
+ // expected-note {{use 'static' to give inline function 'f22' internal linkage}}
+ return a;
+}
+
+int f23(int a) __attribute__((enable_if(sizeof((register T){0}), "enabled"))) { // expected-error {{compound literal in function scope may not be qualified with an address space}}
+ return a;
+}
+
+int f24(int a) __attribute__((enable_if( sizeof((register T){0}), "enabled"))); // expected-error {{compound literal in function scope may not be qualified with an address space}}
+int f24(int a) {
+ return a;
+}
+
+int a24;
+int a25 = sizeof((thread_local static int (*)[a24]){0}); // expected-error {{variably modified type declaration not allowed at file scope}}
+
+int *f25(void) {
+ return &(static int){1};
+}
+
+int *f26(void) {
+ return &(thread_local static int){1};
+}
+
+int *f27(void) {
+ return &(int){1}; // expected-warning {{address of stack memory associated with compound literal '{1}' returned}}
+}
+
+const int *f28(void) {
+ return &(constexpr int){1}; // expected-warning {{address of stack memory associated with compound literal '{1}' returned}}
+}
+
+inline int f29(void) { // expected-note {{use 'static' to give inline function 'f29' internal linkage}}
+ return (thread_local static int){1}; // expected-warning {{non-constant static local variable in inline function may be different in different files}}
+}
+
+void test20(void) {
+ (void)(M const int){1};
+ (void)(constexpr unsigned long){2};
+ (void)sizeof (static int){1};
+ (void)sizeof (static thread_local int){1};
+ (void)sizeof (constexpr int){1};
+}
+
+void test21(void) {
+ (void)(const static int){1}; // expected-error {{type name does not allow storage class to be specified}}
+ (void)(const int register){1}; // expected-error {{type name does not allow storage class to be specified}}
+}
+
+void test22(void) {
+ (void)(auto int){1}; // expected-error {{expected expression}}
+ (void)(extern int){2}; // expected-error {{expected expression}}
+ (void)(typedef int){3}; // expected-error {{expected expression}}
+ (void)(__auto_type int){4}; // expected-error {{expected expression}}
+ (void)(__thread int){5}; // expected-error {{expected expression}}
+}
+
+void test23(void) {
+ (void)(static int constexpr){1}; // expected-error {{type name does not allow constexpr specifier to be specified}}
+ (void)(static int thread_local){1}; // expected-error {{type name does not allow storage class to be specified}}
+ (void)(static int _Thread_local){1}; // expected-error {{type name does not allow storage class to be specified}}
+ (void)(static int __thread){1}; // expected-error {{type name does not allow storage class to be specified}}
+}
+
+void test24(void) {
+ (void)(static int)1; // expected-error {{type name does not allow storage class to be specified}}
+ (void)sizeof(register int); // expected-error {{type name does not allow storage class to be specified}}
+ (void)_Alignof(thread_local int); // expected-error {{type name does not allow storage class to be specified}}
+ (void)(constexpr int)1; // expected-error {{type name does not allow constexpr specifier to be specified}}
+}
+
+int a26 = (static)3; // expected-error {{type name requires a specifier or qualifier}}
+
+typedef int A __attribute__((aligned(64)));
+A *f30(void) {
+ return &(thread_local static A){1}; // ps4-error {{alignment (64) of thread-local compound literal is greater than the maximum supported alignment (32) for thread-local storage on this target}}
+}
diff --git a/clang/test/Sema/c23-compound-literal.m b/clang/test/Sema/c23-compound-literal.m
new file mode 100644
index 0000000000000..142e5a49499eb
--- /dev/null
+++ b/clang/test/Sema/c23-compound-literal.m
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -std=c23 -fobjc-arc -verify %s
+
+typedef struct {
+ id a;
+} S;
+
+void test1(void) {
+ (void)(thread_local static __unsafe_unretained id){0};
+ (void)(thread_local static id){0}; // expected-error {{thread-local variable has non-trivial ownership: type is '__strong id'}}
+ (void)(thread_local static S){0}; // expected-error {{type of thread-local variable has non-trivial destruction}}
+}
diff --git a/clang/test/Sema/constexpr.c b/clang/test/Sema/constexpr.c
index 0a9b5724a8343..936e0a3a32e19 100644
--- a/clang/test/Sema/constexpr.c
+++ b/clang/test/Sema/constexpr.c
@@ -22,7 +22,7 @@ struct S3 {
constexpr; // expected-error {{'constexpr' can only be used in variable declarations}}
constexpr int V1 = 3;
constexpr float V2 = 7.0;
-int V3 = (constexpr)3; // expected-error {{expected expression}}
+int V3 = (constexpr)3; // expected-error {{type name requires a specifier or qualifier}}
void f2() {
constexpr int a = 0;
>From f7af8028bf85cdc59b72cdeeb89fa17379910742 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk <oleksandr.tarasiuk at outlook.com>
Date: Wed, 29 Jul 2026 10:04:08 +0300
Subject: [PATCH 02/21] use hasGlobalStorage for compound literal emission
---
clang/lib/CodeGen/CGExpr.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index fadf00a606f3e..705d2dbb49a80 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -5993,7 +5993,7 @@ CodeGenFunction::EmitLValueForFieldInitialization(LValue Base,
}
LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr *E){
- if (E->isFileScope() || E->hasGlobalStorage()) {
+ if (E->hasGlobalStorage()) {
if (E->getType()->isVariablyModifiedType())
EmitVariablyModifiedType(E->getType());
>From 6ac710f83045b359a0ca12d448480edcd8e418df Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk <oleksandr.tarasiuk at outlook.com>
Date: Wed, 29 Jul 2026 11:32:54 +0300
Subject: [PATCH 03/21] parse all storage-class specifiers in compound literals
---
clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 ++
clang/lib/Parse/ParseExpr.cpp | 15 +++++++++++++++
clang/lib/Sema/SemaExpr.cpp | 11 +++++++++--
clang/test/Sema/c23-compound-literal.c | 6 +++---
4 files changed, 29 insertions(+), 5 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 85528249c4be4..19d086abd8c0e 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3183,6 +3183,8 @@ def err_register_compound_literal_file_scope : Error<
def err_thread_local_compound_literal_without_static : Error<
"compound literal with 'thread_local' storage duration at block scope must "
"also specify 'static'">;
+def err_compound_literal_invalid_storage_class : Error<
+ "storage class specifier '%0' is not permitted in a compound literal">;
def err_constexpr_compound_literal_invalid_type : Error<
"constexpr compound literal cannot have type %0">;
def err_compound_literal_initializer_not_constant : Error<
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 55e1d489efb39..9ae51290fa0ad 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -2660,11 +2660,14 @@ bool Parser::isCompoundLiteralStorageClassSpecifier(const Token &Tok) const {
if (!getLangOpts().C23)
return false;
switch (Tok.getKind()) {
+ case tok::kw_auto:
case tok::kw_constexpr:
+ case tok::kw_extern:
case tok::kw_register:
case tok::kw_static:
case tok::kw_thread_local:
case tok::kw__Thread_local:
+ case tok::kw_typedef:
return true;
default:
return false;
@@ -2680,10 +2683,22 @@ void Parser::ParseCompoundLiteralStorageClassSpecifiers(DeclSpec &DS) {
unsigned DiagID = 0;
bool IsInvalid = false;
switch (Tok.getKind()) {
+ case tok::kw_typedef:
+ IsInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_typedef, Loc,
+ PrevSpec, DiagID, Policy);
+ break;
+ case tok::kw_extern:
+ IsInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_extern, Loc,
+ PrevSpec, DiagID, Policy);
+ break;
case tok::kw_static:
IsInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_static, Loc,
PrevSpec, DiagID, Policy);
break;
+ case tok::kw_auto:
+ IsInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc,
+ PrevSpec, DiagID, Policy);
+ break;
case tok::kw_register:
IsInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_register, Loc,
PrevSpec, DiagID, Policy);
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index b5f19964cbefd..9d2c027e29fa5 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -7533,10 +7533,17 @@ ExprResult Sema::ActOnCompoundLiteral(SourceLocation LParenLoc, ParsedType Ty,
SourceLocation ThreadStorageClassLoc;
SourceLocation ConstexprLoc;
if (DS) {
- if (DS->getStorageClassSpec() == DeclSpec::SCS_static)
+ DeclSpec::SCS StorageClassSpec = DS->getStorageClassSpec();
+ if (StorageClassSpec == DeclSpec::SCS_static)
SC = SC_Static;
- else if (DS->getStorageClassSpec() == DeclSpec::SCS_register)
+ else if (StorageClassSpec == DeclSpec::SCS_register)
SC = SC_Register;
+ else if (StorageClassSpec != DeclSpec::SCS_unspecified) {
+ Diag(DS->getStorageClassSpecLoc(),
+ diag::err_compound_literal_invalid_storage_class)
+ << DeclSpec::getSpecifierName(StorageClassSpec);
+ return ExprError();
+ }
TSC = DS->getThreadStorageClassSpec();
ConstexprKind = DS->getConstexprSpecifier();
diff --git a/clang/test/Sema/c23-compound-literal.c b/clang/test/Sema/c23-compound-literal.c
index 44759108bcd3a..187ea81608b55 100644
--- a/clang/test/Sema/c23-compound-literal.c
+++ b/clang/test/Sema/c23-compound-literal.c
@@ -314,9 +314,9 @@ void test21(void) {
}
void test22(void) {
- (void)(auto int){1}; // expected-error {{expected expression}}
- (void)(extern int){2}; // expected-error {{expected expression}}
- (void)(typedef int){3}; // expected-error {{expected expression}}
+ (void)(auto int){1}; // expected-error {{storage class specifier 'auto' is not permitted in a compound literal}}
+ (void)(extern int){2}; // expected-error {{storage class specifier 'extern' is not permitted in a compound literal}}
+ (void)(typedef int){3}; // expected-error {{storage class specifier 'typedef' is not permitted in a compound literal}}
(void)(__auto_type int){4}; // expected-error {{expected expression}}
(void)(__thread int){5}; // expected-error {{expected expression}}
}
>From 58a103790483ce9d7a688b84fd62d3c1564764cb Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk <oleksandr.tarasiuk at outlook.com>
Date: Wed, 29 Jul 2026 13:25:41 +0300
Subject: [PATCH 04/21] fix compound literal aggrs emit
---
clang/lib/CodeGen/CGExprAgg.cpp | 13 ++++++-------
clang/test/CodeGen/c23-compound-literal.c | 15 +++++++++++++--
2 files changed, 19 insertions(+), 9 deletions(-)
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index c1309c456d4e3..a54ea7c599b1a 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -789,15 +789,14 @@ void AggExprEmitter::VisitOpaqueValueExpr(OpaqueValueExpr *e) {
}
void AggExprEmitter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
- if (E->hasGlobalStorage() || E->getType()->isAtomicType() ||
- (E->getStorageClass() == SC_Register &&
- E->getType().isVolatileQualified()) ||
- Dest.isPotentiallyAliased()) {
+ QualType Ty = E->getType();
+ if (Dest.isPotentiallyAliased() || E->hasGlobalStorage() ||
+ Ty->isAtomicType() || Ty.isVolatileQualified()) {
EmitAggLoadOfLValue(E);
return;
}
- AggValueSlot Slot = EnsureSlot(E->getType());
+ AggValueSlot Slot = EnsureSlot(Ty);
// Block-scope compound literals are destroyed at the end of the enclosing
// scope in C.
@@ -809,9 +808,9 @@ void AggExprEmitter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
CGF.EmitAggExpr(E->getInitializer(), Slot);
if (Destruct)
- if (QualType::DestructionKind DtorKind = E->getType().isDestructedType())
+ if (QualType::DestructionKind DtorKind = Ty.isDestructedType())
CGF.pushLifetimeExtendedDestroy(
- CGF.getCleanupKind(DtorKind), Slot.getAddress(), E->getType(),
+ CGF.getCleanupKind(DtorKind), Slot.getAddress(), Ty,
CGF.getDestroyer(DtorKind), DtorKind & EHCleanup);
}
diff --git a/clang/test/CodeGen/c23-compound-literal.c b/clang/test/CodeGen/c23-compound-literal.c
index d255e72a23d1b..3f542021f5e21 100644
--- a/clang/test/CodeGen/c23-compound-literal.c
+++ b/clang/test/CodeGen/c23-compound-literal.c
@@ -51,11 +51,11 @@ int f6(void) {
}
// CHECK-LABEL: define dso_local i64 @f7()
-// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %retval, ptr align 4 @.compoundliteral.5, i64 8, i1 true)
+// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %retval, ptr align 4 @.compoundliteral.5, i64 8, i1 false)
// CHECK-NEXT: %[[VALUE:.*]] = load i64, ptr %retval, align 4
// CHECK-NEXT: ret i64 %[[VALUE]]
struct S f7(void) {
- return (static volatile struct S){9, 10};
+ return (static struct S){9, 10};
}
// CHECK-LABEL: define dso_local i64 @f8()
@@ -273,3 +273,14 @@ int f28(const int *);
int f29(int a[f28(&(constexpr int){3})]) {
return a[0];
}
+
+// CHECK-LABEL: define dso_local i64 @f30()
+// CHECK: %.compoundliteral = alloca %struct.S
+// CHECK: store i32 19
+// CHECK: store i32 20
+// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %retval, ptr align 4 %.compoundliteral, i64 8, i1 true)
+// CHECK-NEXT: %[[VALUE:.*]] = load i64, ptr %retval, align 4
+// CHECK-NEXT: ret i64 %[[VALUE]]
+struct S f30(void) {
+ return (volatile struct S){19, 20};
+}
>From 203969c6027fa3a91ddbfaad36f091a7b2ce718f Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk <oleksandr.tarasiuk at outlook.com>
Date: Wed, 29 Jul 2026 14:31:14 +0300
Subject: [PATCH 05/21] fix parsing of compound literal storage-class
specifiers
---
clang/include/clang/Parse/Parser.h | 3 ++-
clang/lib/Parse/ParseExpr.cpp | 19 +++++++++++++++----
clang/test/Sema/c23-compound-literal.c | 2 +-
clang/test/Sema/constexpr.c | 2 +-
4 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 43c88344fbb2e..3fd2793eef992 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -5092,7 +5092,8 @@ class Parser : public CodeCompletionHandler {
return isTypeIdInParens(isAmbiguous);
}
- bool isCompoundLiteralStorageClassSpecifier(const Token &Tok) const;
+ bool isCompoundLiteralStorageClassSpecifier() const;
+ bool isCompoundLiteralTypeName();
void ParseCompoundLiteralStorageClassSpecifiers(DeclSpec &DS);
/// Finish parsing a C++ unqualified-id that is a template-id of
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 9ae51290fa0ad..7fb21fdc5ba55 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -2656,7 +2656,7 @@ bool Parser::tryParseOpenMPArrayShapingCastPart() {
return !ErrorFound;
}
-bool Parser::isCompoundLiteralStorageClassSpecifier(const Token &Tok) const {
+bool Parser::isCompoundLiteralStorageClassSpecifier() const {
if (!getLangOpts().C23)
return false;
switch (Tok.getKind()) {
@@ -2674,10 +2674,21 @@ bool Parser::isCompoundLiteralStorageClassSpecifier(const Token &Tok) const {
}
}
+bool Parser::isCompoundLiteralTypeName() {
+ if (!isCompoundLiteralStorageClassSpecifier())
+ return false;
+
+ RevertingTentativeParsingAction TPA(*this);
+ do
+ ConsumeToken();
+ while (isCompoundLiteralStorageClassSpecifier());
+ return isTypeIdInParens();
+}
+
void Parser::ParseCompoundLiteralStorageClassSpecifiers(DeclSpec &DS) {
DS.SetRangeStart(Tok.getLocation());
const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy();
- while (isCompoundLiteralStorageClassSpecifier(Tok)) {
+ while (isCompoundLiteralStorageClassSpecifier()) {
SourceLocation Loc = Tok.getLocation();
const char *PrevSpec = nullptr;
unsigned DiagID = 0;
@@ -2841,7 +2852,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool StopIfCastExpr,
BridgeKeywordLoc, Ty.get(),
RParenLoc, SubExpr.get());
} else if (ExprType >= ParenParseOption::CompoundLiteral &&
- (isCompoundLiteralStorageClassSpecifier(Tok) ||
+ (isCompoundLiteralTypeName() ||
isTypeIdInParens(isAmbiguousTypeId))) {
// Otherwise, this is a compound literal expression or cast expression.
@@ -2859,7 +2870,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool StopIfCastExpr,
}
DeclSpec CompoundDS(AttrFactory);
- if (isCompoundLiteralStorageClassSpecifier(Tok)) {
+ if (isCompoundLiteralStorageClassSpecifier()) {
ParseCompoundLiteralStorageClassSpecifiers(CompoundDS);
CompoundDS.Finish(Actions, Actions.getASTContext().getPrintingPolicy());
}
diff --git a/clang/test/Sema/c23-compound-literal.c b/clang/test/Sema/c23-compound-literal.c
index 187ea81608b55..1310e5a847803 100644
--- a/clang/test/Sema/c23-compound-literal.c
+++ b/clang/test/Sema/c23-compound-literal.c
@@ -335,7 +335,7 @@ void test24(void) {
(void)(constexpr int)1; // expected-error {{type name does not allow constexpr specifier to be specified}}
}
-int a26 = (static)3; // expected-error {{type name requires a specifier or qualifier}}
+int a26 = (static)3; // expected-error {{expected expression}}
typedef int A __attribute__((aligned(64)));
A *f30(void) {
diff --git a/clang/test/Sema/constexpr.c b/clang/test/Sema/constexpr.c
index 936e0a3a32e19..0a9b5724a8343 100644
--- a/clang/test/Sema/constexpr.c
+++ b/clang/test/Sema/constexpr.c
@@ -22,7 +22,7 @@ struct S3 {
constexpr; // expected-error {{'constexpr' can only be used in variable declarations}}
constexpr int V1 = 3;
constexpr float V2 = 7.0;
-int V3 = (constexpr)3; // expected-error {{type name requires a specifier or qualifier}}
+int V3 = (constexpr)3; // expected-error {{expected expression}}
void f2() {
constexpr int a = 0;
>From bb65e74c8cd2d1a00897327dc6a623a63b00badf Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk <oleksandr.tarasiuk at outlook.com>
Date: Fri, 31 Jul 2026 15:53:21 +0300
Subject: [PATCH 06/21] fix compound literal cleanup in params
---
clang/include/clang/AST/Expr.h | 17 +++++++++++------
clang/lib/AST/ASTImporter.cpp | 2 +-
clang/lib/AST/StmtProfile.cpp | 2 +-
clang/lib/CodeGen/CGExpr.cpp | 18 ++++++++++++------
clang/lib/CodeGen/CodeGenFunction.cpp | 4 +---
.../lib/Frontend/Rewrite/RewriteModernObjC.cpp | 9 +++++----
clang/lib/Frontend/Rewrite/RewriteObjC.cpp | 9 +++++----
clang/lib/Sema/SemaExpr.cpp | 13 +++++++++----
clang/lib/Serialization/ASTReaderStmt.cpp | 3 ++-
clang/lib/Serialization/ASTWriterStmt.cpp | 2 +-
10 files changed, 48 insertions(+), 31 deletions(-)
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 6454a750b61c9..0c247e32cb18e 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -3611,6 +3611,10 @@ class MemberExpr final
/// CompoundLiteralExpr - [C99 6.5.2.5, C23 6.5.3.6]
///
class CompoundLiteralExpr : public Expr {
+public:
+ enum class ScopeKind { Block, File, ParameterList };
+
+private:
/// LParenLoc - If non-null, this is the location of the left paren in a
/// compound literal like "(int){4}". This can be null if this is a
/// synthesized compound expression.
@@ -3618,8 +3622,7 @@ class CompoundLiteralExpr : public Expr {
/// The type as written. This can be an incomplete array type, in
/// which case the actual expression type will be different.
- /// The int part of the pair stores whether this expr is file scope.
- llvm::PointerIntPair<TypeSourceInfo *, 1, bool> TInfoAndScope;
+ llvm::PointerIntPair<TypeSourceInfo *, 2, ScopeKind> TInfoAndScope;
Stmt *Init;
/// Value of constant literals with static storage duration.
@@ -3628,11 +3631,11 @@ class CompoundLiteralExpr : public Expr {
public:
CompoundLiteralExpr(
SourceLocation LParenLoc, TypeSourceInfo *TInfo, QualType T,
- ExprValueKind VK, Expr *Init, bool FileScope, StorageClass SC = SC_None,
+ ExprValueKind VK, Expr *Init, ScopeKind Scope, StorageClass SC = SC_None,
ThreadStorageClassSpecifier TSC = TSCS_unspecified,
ConstexprSpecKind ConstexprKind = ConstexprSpecKind::Unspecified)
: Expr(CompoundLiteralExprClass, T, VK, OK_Ordinary),
- LParenLoc(LParenLoc), TInfoAndScope(TInfo, FileScope), Init(Init) {
+ LParenLoc(LParenLoc), TInfoAndScope(TInfo, Scope), Init(Init) {
assert(Init && "Init is a nullptr");
assert((ConstexprKind == ConstexprSpecKind::Unspecified ||
ConstexprKind == ConstexprSpecKind::Constexpr) &&
@@ -3651,8 +3654,10 @@ class CompoundLiteralExpr : public Expr {
Expr *getInitializer() { return cast<Expr>(Init); }
void setInitializer(Expr *E) { Init = E; }
- bool isFileScope() const { return TInfoAndScope.getInt(); }
- void setFileScope(bool FS) { TInfoAndScope.setInt(FS); }
+ ScopeKind getScopeKind() const { return TInfoAndScope.getInt(); }
+ void setScopeKind(ScopeKind Scope) { TInfoAndScope.setInt(Scope); }
+
+ bool isFileScope() const { return getScopeKind() == ScopeKind::File; }
SourceLocation getLParenLoc() const { return LParenLoc; }
void setLParenLoc(SourceLocation L) { LParenLoc = L; }
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 97261a632390b..f0eddbba0ebff 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -8101,7 +8101,7 @@ ExpectedStmt ASTNodeImporter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
return new (Importer.getToContext()) CompoundLiteralExpr(
ToLParenLoc, ToTypeSourceInfo, ToType, E->getValueKind(), ToInitializer,
- E->isFileScope(), E->getStorageClass(), E->getTSCSpec(),
+ E->getScopeKind(), E->getStorageClass(), E->getTSCSpec(),
E->isConstexpr() ? ConstexprSpecKind::Constexpr
: ConstexprSpecKind::Unspecified);
}
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index ef617ddfd49fb..83654ba9ca036 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -1599,7 +1599,7 @@ void StmtProfiler::VisitMemberExpr(const MemberExpr *S) {
void StmtProfiler::VisitCompoundLiteralExpr(const CompoundLiteralExpr *S) {
VisitExpr(S);
- ID.AddBoolean(S->isFileScope());
+ ID.AddInteger(llvm::to_underlying(S->getScopeKind()));
ID.AddInteger(S->getStorageClass());
ID.AddInteger(S->getTSCSpec());
ID.AddBoolean(S->isConstexpr());
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 705d2dbb49a80..bfd21925691f3 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -5992,7 +5992,8 @@ CodeGenFunction::EmitLValueForFieldInitialization(LValue Base,
CGM.getTBAAInfoForSubobject(Base, FieldType));
}
-LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr *E){
+LValue
+CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr *E) {
if (E->hasGlobalStorage()) {
if (E->getType()->isVariablyModifiedType())
EmitVariablyModifiedType(E->getType());
@@ -6021,11 +6022,16 @@ LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr *E){
// Block-scope compound literals are destroyed at the end of the enclosing
// scope in C.
- if (!getLangOpts().CPlusPlus)
- if (QualType::DestructionKind DtorKind = E->getType().isDestructedType())
- pushLifetimeExtendedDestroy(getCleanupKind(DtorKind), DeclPtr,
- E->getType(), getDestroyer(DtorKind),
- DtorKind & EHCleanup);
+ if (!getLangOpts().CPlusPlus) {
+ if (QualType::DestructionKind DtorKind = E->getType().isDestructedType()) {
+ if (E->getScopeKind() == CompoundLiteralExpr::ScopeKind::ParameterList)
+ pushDestroy(DtorKind, DeclPtr, E->getType());
+ else
+ pushLifetimeExtendedDestroy(getCleanupKind(DtorKind), DeclPtr,
+ E->getType(), getDestroyer(DtorKind),
+ DtorKind & EHCleanup);
+ }
+ }
return Result;
}
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 861dfa1f9f1c7..119aebb673789 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -1360,10 +1360,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
else
Ty = VD->getType();
- if (Ty->isVariablyModifiedType()) {
- RunCleanupsScope Scope(*this);
+ if (Ty->isVariablyModifiedType())
EmitVariablyModifiedType(Ty);
- }
}
}
// Emit a location at the end of the prologue.
diff --git a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
index 12442040b13bb..3ebb54ac372aa 100644
--- a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
+++ b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
@@ -3298,9 +3298,9 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
SourceLocation(), /*isExplicit=*/true);
TypeSourceInfo *superTInfo
= Context->getTrivialTypeSourceInfo(superType);
- SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo,
- superType, VK_LValue,
- ILE, false);
+ SuperRep = new (Context) CompoundLiteralExpr(
+ SourceLocation(), superTInfo, superType, VK_LValue, ILE,
+ CompoundLiteralExpr::ScopeKind::Block);
// struct __rw_objc_super *
SuperRep = UnaryOperator::Create(
const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
@@ -3391,7 +3391,8 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
TypeSourceInfo *superTInfo
= Context->getTrivialTypeSourceInfo(superType);
SuperRep = new (Context) CompoundLiteralExpr(
- SourceLocation(), superTInfo, superType, VK_PRValue, ILE, false);
+ SourceLocation(), superTInfo, superType, VK_PRValue, ILE,
+ CompoundLiteralExpr::ScopeKind::Block);
}
MsgExprs.push_back(SuperRep);
break;
diff --git a/clang/lib/Frontend/Rewrite/RewriteObjC.cpp b/clang/lib/Frontend/Rewrite/RewriteObjC.cpp
index 6b8753e29b8fe..d540a5830ee33 100644
--- a/clang/lib/Frontend/Rewrite/RewriteObjC.cpp
+++ b/clang/lib/Frontend/Rewrite/RewriteObjC.cpp
@@ -2726,9 +2726,9 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
SourceLocation(), /*isExplicit=*/true);
TypeSourceInfo *superTInfo
= Context->getTrivialTypeSourceInfo(superType);
- SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo,
- superType, VK_LValue,
- ILE, false);
+ SuperRep = new (Context) CompoundLiteralExpr(
+ SourceLocation(), superTInfo, superType, VK_LValue, ILE,
+ CompoundLiteralExpr::ScopeKind::Block);
// struct objc_super *
SuperRep = UnaryOperator::Create(
const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
@@ -2819,7 +2819,8 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
TypeSourceInfo *superTInfo
= Context->getTrivialTypeSourceInfo(superType);
SuperRep = new (Context) CompoundLiteralExpr(
- SourceLocation(), superTInfo, superType, VK_PRValue, ILE, false);
+ SourceLocation(), superTInfo, superType, VK_PRValue, ILE,
+ CompoundLiteralExpr::ScopeKind::Block);
}
MsgExprs.push_back(SuperRep);
break;
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 9d2c027e29fa5..0f54f4b3db016 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -7715,6 +7715,10 @@ ExprResult Sema::BuildCompoundLiteralExpr(
(getLangOpts().CPlusPlus && !(IsFileScope && literalType->isArrayType()))
? VK_PRValue
: VK_LValue;
+ CompoundLiteralExpr::ScopeKind Scope =
+ IsFileScope ? CompoundLiteralExpr::ScopeKind::File
+ : IsPrototypeScope ? CompoundLiteralExpr::ScopeKind::ParameterList
+ : CompoundLiteralExpr::ScopeKind::Block;
bool HasGlobalStorage =
IsFileScope || (getLangOpts().C23 && (HasStatic || HasThreadStorage));
@@ -7749,8 +7753,8 @@ ExprResult Sema::BuildCompoundLiteralExpr(
}
auto *E = new (Context)
- CompoundLiteralExpr(LParenLoc, TInfo, literalType, VK, LiteralExpr,
- IsFileScope, SC, TSC, ConstexprKind);
+ CompoundLiteralExpr(LParenLoc, TInfo, literalType, VK, LiteralExpr, Scope,
+ SC, TSC, ConstexprKind);
if (HasGlobalStorage && !HasConstexpr) {
if (!LiteralExpr->isTypeDependent() && !LiteralExpr->isValueDependent() &&
@@ -10332,8 +10336,9 @@ static void ConstructTransparentUnion(Sema &S, ASTContext &C,
// Build a compound literal constructing a value of the transparent
// union type from this initializer list.
TypeSourceInfo *unionTInfo = C.getTrivialTypeSourceInfo(UnionType);
- EResult = new (C) CompoundLiteralExpr(SourceLocation(), unionTInfo, UnionType,
- VK_PRValue, Initializer, false);
+ EResult = new (C)
+ CompoundLiteralExpr(SourceLocation(), unionTInfo, UnionType, VK_PRValue,
+ Initializer, CompoundLiteralExpr::ScopeKind::Block);
}
AssignConvertType
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index 2e8c055a8ac6a..0f75089075056 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -1238,7 +1238,8 @@ void ASTStmtReader::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
E->setLParenLoc(readSourceLocation());
E->setTypeSourceInfo(readTypeSourceInfo());
E->setInitializer(Record.readSubExpr());
- E->setFileScope(Record.readInt());
+ E->setScopeKind(
+ static_cast<CompoundLiteralExpr::ScopeKind>(Record.readInt()));
E->setStorageClass(static_cast<StorageClass>(Record.readInt()));
E->setTSCSpec(static_cast<ThreadStorageClassSpecifier>(Record.readInt()));
E->setConstexpr(Record.readInt());
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index f0ff9eb1ed80f..49470190cfd34 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -1205,7 +1205,7 @@ void ASTStmtWriter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
Record.AddSourceLocation(E->getLParenLoc());
Record.AddTypeSourceInfo(E->getTypeSourceInfo());
Record.AddStmt(E->getInitializer());
- Record.push_back(E->isFileScope());
+ Record.push_back(llvm::to_underlying(E->getScopeKind()));
Record.push_back(E->getStorageClass());
Record.push_back(E->getTSCSpec());
Record.push_back(E->isConstexpr());
>From 703ba4068fb2bf9d1cb91ceca19864d9dab38d10 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk <oleksandr.tarasiuk at outlook.com>
Date: Sat, 1 Aug 2026 10:50:11 +0300
Subject: [PATCH 07/21] add additional tests
---
clang/test/Sema/c23-compound-literal.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/clang/test/Sema/c23-compound-literal.c b/clang/test/Sema/c23-compound-literal.c
index 1310e5a847803..d171f51cfc011 100644
--- a/clang/test/Sema/c23-compound-literal.c
+++ b/clang/test/Sema/c23-compound-literal.c
@@ -319,6 +319,7 @@ void test22(void) {
(void)(typedef int){3}; // expected-error {{storage class specifier 'typedef' is not permitted in a compound literal}}
(void)(__auto_type int){4}; // expected-error {{expected expression}}
(void)(__thread int){5}; // expected-error {{expected expression}}
+ (void)(auto){1}; // expected-error {{expected expression}}
}
void test23(void) {
@@ -326,6 +327,7 @@ void test23(void) {
(void)(static int thread_local){1}; // expected-error {{type name does not allow storage class to be specified}}
(void)(static int _Thread_local){1}; // expected-error {{type name does not allow storage class to be specified}}
(void)(static int __thread){1}; // expected-error {{type name does not allow storage class to be specified}}
+ (void)(int static){1}; // expected-error {{type name does not allow storage class to be specified}}
}
void test24(void) {
>From 3484d56d2150b409006b123438d75a4f2428f2de Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk <oleksandr.tarasiuk at outlook.com>
Date: Sat, 1 Aug 2026 10:55:37 +0300
Subject: [PATCH 08/21] remove redundant file-scope checks
---
clang/lib/CodeGen/CGExprConstant.cpp | 2 +-
clang/lib/Sema/CheckExprLifetime.cpp | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp
index 2123eab890779..e87f0b93f7d29 100644
--- a/clang/lib/CodeGen/CGExprConstant.cpp
+++ b/clang/lib/CodeGen/CGExprConstant.cpp
@@ -1089,7 +1089,7 @@ tryEmitGlobalCompoundLiteral(ConstantEmitter &emitter,
llvm::Constant *C = emitter.tryEmitForInitializer(E->getInitializer(),
addressSpace, E->getType());
if (!C) {
- assert(!E->isFileScope() && !E->hasGlobalStorage() &&
+ assert(!E->hasGlobalStorage() &&
"global compound literal did not have constant initializer!");
return ConstantAddress::invalid();
}
diff --git a/clang/lib/Sema/CheckExprLifetime.cpp b/clang/lib/Sema/CheckExprLifetime.cpp
index e5cfc3086fb58..8007537075617 100644
--- a/clang/lib/Sema/CheckExprLifetime.cpp
+++ b/clang/lib/Sema/CheckExprLifetime.cpp
@@ -659,7 +659,7 @@ static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path,
case Stmt::CompoundLiteralExprClass: {
if (auto *CLE = dyn_cast<CompoundLiteralExpr>(Init)) {
- if (!CLE->isFileScope() && !CLE->hasGlobalStorage())
+ if (!CLE->hasGlobalStorage())
Visit(Path, Local(CLE), RK);
}
break;
>From d294ccf443945662a5f97169638e6cd891b54d5c Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk <oleksandr.tarasiuk at outlook.com>
Date: Sat, 1 Aug 2026 11:02:19 +0300
Subject: [PATCH 09/21] use EvaluationMode for C23 const evaluation
---
clang/include/clang/AST/Expr.h | 2 --
clang/lib/AST/ExprConstant.cpp | 22 +++++-----------------
clang/lib/Sema/SemaExpr.cpp | 4 +---
3 files changed, 6 insertions(+), 22 deletions(-)
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 0c247e32cb18e..585f80fa35aed 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -765,8 +765,6 @@ class Expr : public ValueStmt {
/// evaluation is not part of the evaluation, but all other temporaries
/// are destroyed.
ImmediateInvocation,
- /// The initializer of a compound literal constant.
- CompoundLiteralInitializer,
};
/// Evaluate an expression that is required to be a constant expression. Does
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 98e9bb69584f3..d13110bf1abb5 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -157,7 +157,6 @@ namespace {
case ConstantExprKind::Normal:
case ConstantExprKind::ClassTemplateArgument:
case ConstantExprKind::ImmediateInvocation:
- case ConstantExprKind::CompoundLiteralInitializer:
// Note that non-type template arguments of class type are emitted as
// template parameter objects.
return false;
@@ -172,7 +171,6 @@ namespace {
switch (Kind) {
case ConstantExprKind::Normal:
case ConstantExprKind::ImmediateInvocation:
- case ConstantExprKind::CompoundLiteralInitializer:
return false;
case ConstantExprKind::ClassTemplateArgument:
@@ -815,8 +813,6 @@ namespace {
/// not supported by the interpreter, an error is triggered.
bool EnableNewConstInterp;
- ConstantExprKind ConstantKind;
-
/// BottomFrame - The frame in which evaluation started. This must be
/// initialized after CurrentCall and CallStackDepth.
CallStackFrame BottomFrame;
@@ -917,13 +913,11 @@ namespace {
/// initialization.
uint64_t ArrayInitIndex = -1;
- EvalInfo(const ASTContext &C, Expr::EvalStatus &S, EvaluationMode Mode,
- ConstantExprKind Kind = ConstantExprKind::Normal)
+ EvalInfo(const ASTContext &C, Expr::EvalStatus &S, EvaluationMode Mode)
: State(const_cast<ASTContext &>(C), S), CurrentCall(nullptr),
CallStackDepth(0), NextCallIndex(1),
StepsLeft(C.getLangOpts().ConstexprStepLimit),
EnableNewConstInterp(C.getLangOpts().EnableNewConstInterp),
- ConstantKind(Kind),
BottomFrame(*this, SourceLocation(), /*Callee=*/nullptr,
/*This=*/nullptr,
/*CallExpr=*/nullptr, CallRef()),
@@ -4663,12 +4657,6 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
}
bool IsAccess = isAnyAccess(AK);
- bool IsConstexprInitializer =
- Info.ConstantKind == ConstantExprKind::CompoundLiteralInitializer;
- if (const auto *VD = dyn_cast_if_present<VarDecl>(
- Info.EvaluatingDecl.dyn_cast<const ValueDecl *>()))
- IsConstexprInitializer |= VD->isConstexpr();
-
// C++11 DR1311: An lvalue-to-rvalue conversion on a volatile-qualified type
// is not a constant expression (even if the object is non-volatile). We also
// apply this rule to C++98, in order to conform to the expected 'volatile'
@@ -4765,7 +4753,8 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
return CompleteObject();
} else if (VD->isConstexpr()) {
// OK, we can read this variable.
- } else if (Info.getLangOpts().C23 && IsConstexprInitializer) {
+ } else if (Info.getLangOpts().C23 &&
+ Info.EvalMode == EvaluationMode::ConstantExpression) {
Info.FFDiag(E);
return CompleteObject();
} else if (BaseType->isIntegralOrEnumerationType()) {
@@ -22000,14 +21989,13 @@ bool Expr::EvaluateAsConstantExpr(EvalResult &Result, const ASTContext &Ctx,
assert(!isValueDependent() &&
"Expression evaluator can't be called on a dependent expression.");
bool IsConst;
- if (Kind != ConstantExprKind::CompoundLiteralInitializer &&
- FastEvaluateAsRValue(this, Result.Val, Ctx, IsConst) &&
+ if (FastEvaluateAsRValue(this, Result.Val, Ctx, IsConst) &&
Result.Val.hasValue())
return true;
ExprTimeTraceScope TimeScope(this, Ctx, "EvaluateAsConstantExpr");
EvaluationMode EM = EvaluationMode::ConstantExpression;
- EvalInfo Info(Ctx, Result, EM, Kind);
+ EvalInfo Info(Ctx, Result, EM);
Info.InConstantContext = true;
if (Info.EnableNewConstInterp) {
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 0f54f4b3db016..527907de8ab8e 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -7675,9 +7675,7 @@ ExprResult Sema::BuildCompoundLiteralExpr(
SmallVector<PartialDiagnosticAt, 4> Notes;
Expr::EvalResult Eval;
Eval.Diag = &Notes;
- if (!LiteralExpr->EvaluateAsConstantExpr(
- Eval, Context,
- Expr::ConstantExprKind::CompoundLiteralInitializer) ||
+ if (!LiteralExpr->EvaluateAsConstantExpr(Eval, Context) ||
Notes.size() > 0) {
SourceLocation DiagLoc = ConstexprLoc;
if (Notes.size() == 1 && Notes.front().second.getDiagID() ==
>From 2f98d2df32b609aea352738a20faf69c91b478ed Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk <oleksandr.tarasiuk at outlook.com>
Date: Tue, 4 Aug 2026 16:52:40 +0300
Subject: [PATCH 10/21] handle compound literals in the constexpr interpreter
---
clang/lib/AST/ByteCode/Compiler.cpp | 5 ++++-
clang/lib/AST/ByteCode/Interp.cpp | 27 ++++++++++++++++++--------
clang/test/Sema/c23-compound-literal.c | 1 +
3 files changed, 24 insertions(+), 9 deletions(-)
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index e72e7875f6937..156a77132c554 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -3613,6 +3613,9 @@ bool Compiler<Emitter>::VisitCXXBindTemporaryExpr(
template <class Emitter>
bool Compiler<Emitter>::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) {
const Expr *Init = E->getInitializer();
+ if (E->hasThreadStorage())
+ return this->emitInvalid(E);
+
if (DiscardResult)
return this->discard(Init);
@@ -3622,7 +3625,7 @@ bool Compiler<Emitter>::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) {
}
OptPrimType T = classify(E->getType());
- if (E->isFileScope()) {
+ if (E->hasGlobalStorage()) {
// Avoid creating a variable if this is a primitive RValue anyway.
if (T && !E->isLValue())
return this->delegate(Init);
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index 475d206356de8..2a21f28c485ee 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -460,10 +460,24 @@ bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
return true;
}
+static bool CheckConstexprVar(InterpState &S, CodePtr OpPC,
+ const Descriptor *Desc) {
+ const auto *VD = Desc->asVarDecl();
+ if (!VD)
+ return true;
+ if (S.getLangOpts().C23 && S.EvalMode == EvaluationMode::ConstantExpression &&
+ VD != S.EvaluatingDecl && !VD->isConstexpr())
+ return Invalid(S, OpPC);
+ return true;
+}
+
bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc,
AccessKinds AK) {
assert(Desc);
+ if (!CheckConstexprVar(S, OpPC, Desc))
+ return false;
+
const auto *D = Desc->asVarDecl();
if (S.checkingConstantDestruction(D)) {
// If we're checking for a constant destructor for this variable, we can
@@ -473,13 +487,6 @@ bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc,
} else if (!D || D == S.EvaluatingDecl || D->isConstexpr())
return true;
- // If we're evaluating the initializer for a constexpr variable in C23, we may
- // only read other contexpr variables. Abort here since this one isn't
- // constexpr.
- if (const auto *VD = S.EvaluatingDecl;
- VD && VD->isConstexpr() && S.getLangOpts().C23)
- return Invalid(S, OpPC);
-
QualType T = D->getType();
bool IsConstant = T.isConstant(S.getASTContext());
if (T->isIntegralOrEnumerationType()) {
@@ -523,8 +530,10 @@ static bool CheckConstant(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
if (S.checkingConstantDestruction(Ptr))
return CheckConstant(S, OpPC, Ptr.getDeclDesc(), AK);
- if (!Ptr.isStatic() || !Ptr.isBlockPointer())
+ if (!Ptr.isBlockPointer())
return true;
+ if (!Ptr.isStatic())
+ return CheckConstexprVar(S, OpPC, Ptr.getDeclDesc());
if (!Ptr.getDeclID())
return true;
return CheckConstant(S, OpPC, Ptr.getDeclDesc(), AK);
@@ -859,6 +868,8 @@ bool CheckLocalLoad(InterpState &S, CodePtr OpPC, const Block *B) {
assert(!B->isExtern());
const auto &Desc = *reinterpret_cast<const InlineDescriptor *>(B->rawData());
const Descriptor *BlockDesc = B->getDescriptor();
+ if (!CheckConstexprVar(S, OpPC, BlockDesc))
+ return false;
if (!Desc.IsInitialized)
return diagnoseUninitialized(S, OpPC, /*Extern=*/false, B, Desc.LifeState);
if (!CheckLifetime(S, OpPC, Desc.LifeState, B, AK_Read))
diff --git a/clang/test/Sema/c23-compound-literal.c b/clang/test/Sema/c23-compound-literal.c
index d171f51cfc011..1fe4210f036ba 100644
--- a/clang/test/Sema/c23-compound-literal.c
+++ b/clang/test/Sema/c23-compound-literal.c
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -std=c23 -triple x86_64-unknown-linux-gnu -verify -fsyntax-only %s
+// RUN: %clang_cc1 -std=c23 -triple x86_64-unknown-linux-gnu -verify -fsyntax-only -fexperimental-new-constant-interpreter %s
// RUN: %clang_cc1 -std=c23 -triple x86_64-scei-ps4 -verify=expected,ps4 -fsyntax-only %s
#define M static
>From 94143f862a2bc07c01b24b24bac7033947793bb8 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk <oleksandr.tarasiuk at outlook.com>
Date: Tue, 1 Sep 2026 09:38:07 +0300
Subject: [PATCH 11/21] reuse storage-class mapping
---
clang/include/clang/Sema/Sema.h | 4 ++++
clang/lib/Sema/SemaDecl.cpp | 6 +-----
clang/lib/Sema/SemaExpr.cpp | 9 ++++-----
3 files changed, 9 insertions(+), 10 deletions(-)
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index b8e4ba6f3f474..b0a3899b560fb 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -4038,6 +4038,10 @@ class Sema final : public SemaBase {
ArrayRef<BindingDecl *> Bindings = {});
private:
+ /// Maps a DeclSpec::SCS to a VarDecl::StorageClass. Any error reporting is up
+ /// to the caller; illegal input values are mapped to SC_None.
+ static StorageClass StorageClassSpecToVarDeclStorageClass(const DeclSpec &DS);
+
// Perform a check on an AsmLabel to verify its consistency and emit
// diagnostics in case of an error.
void CheckAsmLabel(Scope *S, Expr *AsmLabelExpr, StorageClass SC,
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 9264be70578ea..5118966186fd1 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -5666,11 +5666,7 @@ InjectAnonymousStructOrUnionMembers(Sema &SemaRef, Scope *S, DeclContext *Owner,
return Invalid;
}
-/// StorageClassSpecToVarDeclStorageClass - Maps a DeclSpec::SCS to
-/// a VarDecl::StorageClass. Any error reporting is up to the caller:
-/// illegal input values are mapped to SC_None.
-static StorageClass
-StorageClassSpecToVarDeclStorageClass(const DeclSpec &DS) {
+StorageClass Sema::StorageClassSpecToVarDeclStorageClass(const DeclSpec &DS) {
DeclSpec::SCS StorageClassSpec = DS.getStorageClassSpec();
assert(StorageClassSpec != DeclSpec::SCS_typedef &&
"Parser allowed 'typedef' as storage class VarDecl.");
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index b1ed4c0977cc8..b3721f07a173e 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -7534,16 +7534,15 @@ ExprResult Sema::ActOnCompoundLiteral(SourceLocation LParenLoc, ParsedType Ty,
SourceLocation ConstexprLoc;
if (DS) {
DeclSpec::SCS StorageClassSpec = DS->getStorageClassSpec();
- if (StorageClassSpec == DeclSpec::SCS_static)
- SC = SC_Static;
- else if (StorageClassSpec == DeclSpec::SCS_register)
- SC = SC_Register;
- else if (StorageClassSpec != DeclSpec::SCS_unspecified) {
+ if (StorageClassSpec != DeclSpec::SCS_unspecified &&
+ StorageClassSpec != DeclSpec::SCS_static &&
+ StorageClassSpec != DeclSpec::SCS_register) {
Diag(DS->getStorageClassSpecLoc(),
diag::err_compound_literal_invalid_storage_class)
<< DeclSpec::getSpecifierName(StorageClassSpec);
return ExprError();
}
+ SC = StorageClassSpecToVarDeclStorageClass(*DS);
TSC = DS->getThreadStorageClassSpec();
ConstexprKind = DS->getConstexprSpecifier();
>From 8186617dc0cdaf71d218fe2d9a4550cca2be4d4e Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk <oleksandr.tarasiuk at outlook.com>
Date: Tue, 1 Sep 2026 11:10:22 +0300
Subject: [PATCH 12/21] refactor SCS parsing
---
clang/include/clang/AST/Expr.h | 4 +-
clang/include/clang/Parse/Parser.h | 7 +-
clang/lib/Parse/ParseDecl.cpp | 242 ++++++++++++--------
clang/lib/Parse/ParseExpr.cpp | 63 +----
clang/test/AST/c23-compound-literal-print.c | 4 +-
clang/test/CodeGen/c23-compound-literal.c | 8 +
clang/test/Sema/c23-compound-literal.c | 8 +-
7 files changed, 173 insertions(+), 163 deletions(-)
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 585f80fa35aed..133171c49ff63 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -3696,8 +3696,8 @@ class CompoundLiteralExpr : public Expr {
}
void setTSCSpec(ThreadStorageClassSpecifier TSC) {
- assert((TSC == TSCS_unspecified || TSC == TSCS_thread_local ||
- TSC == TSCS__Thread_local) &&
+ assert((TSC == TSCS_unspecified || TSC == TSCS___thread ||
+ TSC == TSCS_thread_local || TSC == TSCS__Thread_local) &&
"invalid compound literal thread storage class");
CompoundLiteralExprBits.TSCSpec = TSC;
assert(getTSCSpec() == TSC && "truncation");
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index d2396fbf5cd20..47d7ca1c3a605 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -1884,6 +1884,11 @@ class Parser : public CodeCompletionHandler {
/// DeclaratorContext enumerator values.
DeclSpecContext
getDeclSpecContextFromDeclaratorContext(DeclaratorContext Context);
+
+ enum class StorageClassSpecifierContext { Declaration, CompoundLiteral };
+ void ParseStorageClassSpecifier(DeclSpec &DS,
+ StorageClassSpecifierContext Context);
+
void
ParseDeclarationSpecifiers(DeclSpec &DS, ParsedTemplateInfo &TemplateInfo,
AccessSpecifier AS = AS_none,
@@ -5095,7 +5100,7 @@ class Parser : public CodeCompletionHandler {
}
bool isCompoundLiteralStorageClassSpecifier() const;
- bool isCompoundLiteralTypeName();
+ bool isTypeIdInParensWithStorageClassSpecifiers();
void ParseCompoundLiteralStorageClassSpecifiers(DeclSpec &DS);
/// Finish parsing a C++ unqualified-id that is a template-id of
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 9fa3b96527c08..8389aae8e0e23 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -3379,6 +3379,138 @@ Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS,
return false;
}
+void Parser::ParseStorageClassSpecifier(DeclSpec &DS,
+ StorageClassSpecifierContext Context) {
+ SourceLocation Loc = Tok.getLocation();
+ const char *PrevSpec = nullptr;
+ unsigned DiagID = 0;
+ bool IsInvalid = false;
+ PrintingPolicy Policy = Actions.getPrintingPolicy();
+
+ switch (Tok.getKind()) {
+ case tok::kw_typedef:
+ IsInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_typedef, Loc,
+ PrevSpec, DiagID, Policy);
+ break;
+ case tok::kw_extern:
+ if (DS.getThreadStorageClassSpec() == DeclSpec::TSCS___thread)
+ Diag(Tok, diag::ext_thread_before) << "extern";
+ IsInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_extern, Loc,
+ PrevSpec, DiagID, Policy);
+ break;
+ case tok::kw___private_extern__:
+ IsInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_private_extern,
+ Loc, PrevSpec, DiagID, Policy);
+ break;
+ case tok::kw_static:
+ if (DS.getThreadStorageClassSpec() == DeclSpec::TSCS___thread)
+ Diag(Tok, diag::ext_thread_before) << "static";
+ IsInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_static, Loc,
+ PrevSpec, DiagID, Policy);
+ break;
+ case tok::kw_auto:
+ if (getLangOpts().CPlusPlus11 || getLangOpts().C23) {
+ auto MayBeTypeSpecifier = [&]() {
+ // In pre-C23 C, auto can be used as a storage-class specifier.
+ // C23 removes auto from the storage-class specifiers and repurposes
+ // it for type inference (6.7.10).
+ if (getLangOpts().C23 && DS.hasTypeSpecifier() &&
+ DS.getTypeSpecType() != DeclSpec::TST_auto)
+ return true;
+
+ unsigned I = 1;
+ while (true) {
+ const Token &T = GetLookAheadToken(I);
+ if (isKnownToBeTypeSpecifier(T))
+ return true;
+
+ if (getLangOpts().C23 && isTypeSpecifierQualifier(T))
+ ++I;
+ else
+ return false;
+ }
+ };
+
+ if (!getLangOpts().CPlusPlus && MayBeTypeSpecifier()) {
+ IsInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc,
+ PrevSpec, DiagID, Policy);
+ } else {
+ if (getLangOpts().CPlusPlus11 &&
+ NextToken().isOneOf(tok::kw_class, tok::kw_struct,
+ tok::kw___interface, tok::kw_union,
+ tok::kw_enum))
+ Diag(Loc, diag::ext_auto_storage_class);
+ IsInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec,
+ DiagID, Policy);
+ }
+ } else {
+ IsInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc,
+ PrevSpec, DiagID, Policy);
+ }
+ break;
+ case tok::kw_register:
+ IsInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_register, Loc,
+ PrevSpec, DiagID, Policy);
+ break;
+ case tok::kw_mutable:
+ IsInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_mutable, Loc,
+ PrevSpec, DiagID, Policy);
+ break;
+ case tok::kw___thread:
+ IsInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS___thread, Loc,
+ PrevSpec, DiagID);
+ break;
+ case tok::kw_thread_local:
+ if (Context == StorageClassSpecifierContext::Declaration &&
+ getLangOpts().C23)
+ Diag(Tok, diag::warn_c23_compat_keyword) << Tok.getName();
+ // We map thread_local to _Thread_local in C23 mode so it retains the C
+ // semantics rather than getting the C++ semantics.
+ // FIXME: diagnostics will show _Thread_local when the user wrote
+ // thread_local in source in C23 mode; we need some general way to
+ // identify which way the user spelled the keyword in source.
+ IsInvalid = DS.SetStorageClassSpecThread(getLangOpts().C23
+ ? DeclSpec::TSCS__Thread_local
+ : DeclSpec::TSCS_thread_local,
+ Loc, PrevSpec, DiagID);
+ break;
+ case tok::kw__Thread_local:
+ diagnoseUseOfC11Keyword(Tok);
+ IsInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS__Thread_local, Loc,
+ PrevSpec, DiagID);
+ break;
+ case tok::kw_constexpr:
+ if (Context == StorageClassSpecifierContext::Declaration &&
+ getLangOpts().C23)
+ Diag(Tok, diag::warn_c23_compat_keyword) << Tok.getName();
+ IsInvalid = DS.SetConstexprSpec(ConstexprSpecKind::Constexpr, Loc, PrevSpec,
+ DiagID);
+ break;
+ default:
+ llvm_unreachable("not a storage class specifier");
+ }
+
+ DS.SetRangeEnd(Loc);
+ if (IsInvalid && !DS.hasConflictingTypeSpecifier()) {
+ assert(PrevSpec && "Method did not return previous specifier!");
+ assert(DiagID);
+
+ if (DiagID == diag::ext_duplicate_declspec ||
+ DiagID == diag::ext_warn_duplicate_declspec ||
+ DiagID == diag::err_duplicate_declspec)
+ Diag(Loc, DiagID) << PrevSpec
+ << FixItHint::CreateRemoval(
+ SourceRange(Loc, DS.getEndLoc()));
+ else if (DiagID == diag::err_opencl_unknown_type_specifier)
+ Diag(Loc, DiagID) << getLangOpts().getOpenCLVersionString() << PrevSpec
+ << /*IsStorageClass=*/true;
+ else
+ Diag(Loc, DiagID) << PrevSpec;
+ }
+
+ ConsumeToken();
+}
+
void Parser::ParseDeclarationSpecifiers(
DeclSpec &DS, ParsedTemplateInfo &TemplateInfo, AccessSpecifier AS,
DeclSpecContext DSContext, LateParsedAttrList *LateAttrs,
@@ -4122,108 +4254,24 @@ void Parser::ParseDeclarationSpecifiers(
// storage-class-specifier
case tok::kw_typedef:
- isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_typedef, Loc,
- PrevSpec, DiagID, Policy);
- isStorageClass = true;
- break;
case tok::kw_extern:
- if (DS.getThreadStorageClassSpec() == DeclSpec::TSCS___thread)
- Diag(Tok, diag::ext_thread_before) << "extern";
- isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_extern, Loc,
- PrevSpec, DiagID, Policy);
- isStorageClass = true;
- break;
case tok::kw___private_extern__:
- isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_private_extern,
- Loc, PrevSpec, DiagID, Policy);
- isStorageClass = true;
- break;
case tok::kw_static:
- if (DS.getThreadStorageClassSpec() == DeclSpec::TSCS___thread)
- Diag(Tok, diag::ext_thread_before) << "static";
- isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_static, Loc,
- PrevSpec, DiagID, Policy);
- isStorageClass = true;
- break;
case tok::kw_auto:
- if (getLangOpts().CPlusPlus11 || getLangOpts().C23) {
- auto MayBeTypeSpecifier = [&]() {
- // In pre-C23 C, auto can be used as a storage-class specifier.
- // C23 removes auto from the storage-class specifiers and repurposes
- // it for type inference (6.7.10).
- if (getLangOpts().C23 && DS.hasTypeSpecifier() &&
- DS.getTypeSpecType() != DeclSpec::TST_auto)
- return true;
-
- unsigned I = 1;
- while (true) {
- const Token &T = GetLookAheadToken(I);
- if (isKnownToBeTypeSpecifier(T))
- return true;
-
- if (getLangOpts().C23 && isTypeSpecifierQualifier(T))
- ++I;
- else
- return false;
- }
- };
-
- if (!getLangOpts().CPlusPlus && MayBeTypeSpecifier()) {
- isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc,
- PrevSpec, DiagID, Policy);
- } else {
- if (getLangOpts().CPlusPlus11 &&
- NextToken().isOneOf(tok::kw_class, tok::kw_struct,
- tok::kw___interface, tok::kw_union,
- tok::kw_enum))
- Diag(Loc, diag::ext_auto_storage_class);
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec,
- DiagID, Policy);
- }
- } else
- isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc,
- PrevSpec, DiagID, Policy);
- isStorageClass = true;
- break;
- case tok::kw___auto_type:
- Diag(Tok, diag::ext_auto_type);
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto_type, Loc, PrevSpec,
- DiagID, Policy);
- break;
case tok::kw_register:
- isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_register, Loc,
- PrevSpec, DiagID, Policy);
- isStorageClass = true;
- break;
case tok::kw_mutable:
- isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_mutable, Loc,
- PrevSpec, DiagID, Policy);
- isStorageClass = true;
- break;
case tok::kw___thread:
- isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS___thread, Loc,
- PrevSpec, DiagID);
- isStorageClass = true;
- break;
case tok::kw_thread_local:
- if (getLangOpts().C23)
- Diag(Tok, diag::warn_c23_compat_keyword) << Tok.getName();
- // We map thread_local to _Thread_local in C23 mode so it retains the C
- // semantics rather than getting the C++ semantics.
- // FIXME: diagnostics will show _Thread_local when the user wrote
- // thread_local in source in C23 mode; we need some general way to
- // identify which way the user spelled the keyword in source.
- isInvalid = DS.SetStorageClassSpecThread(
- getLangOpts().C23 ? DeclSpec::TSCS__Thread_local
- : DeclSpec::TSCS_thread_local,
- Loc, PrevSpec, DiagID);
- isStorageClass = true;
- break;
case tok::kw__Thread_local:
- diagnoseUseOfC11Keyword(Tok);
- isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS__Thread_local,
- Loc, PrevSpec, DiagID);
- isStorageClass = true;
+ case tok::kw_constexpr:
+ ParseStorageClassSpecifier(DS, StorageClassSpecifierContext::Declaration);
+ AttrsLastTime = false;
+ continue;
+
+ case tok::kw___auto_type:
+ Diag(Tok, diag::ext_auto_type);
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto_type, Loc, PrevSpec,
+ DiagID, Policy);
break;
// function-specifier
@@ -4307,13 +4355,7 @@ void Parser::ParseDeclarationSpecifiers(
isInvalid = DS.setModulePrivateSpec(Loc, PrevSpec, DiagID);
break;
- // constexpr, consteval, constinit specifiers
- case tok::kw_constexpr:
- if (getLangOpts().C23)
- Diag(Tok, diag::warn_c23_compat_keyword) << Tok.getName();
- isInvalid = DS.SetConstexprSpec(ConstexprSpecKind::Constexpr, Loc,
- PrevSpec, DiagID);
- break;
+ // consteval and constinit specifiers
case tok::kw_consteval:
isInvalid = DS.SetConstexprSpec(ConstexprSpecKind::Consteval, Loc,
PrevSpec, DiagID);
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 7fb21fdc5ba55..d713ac2615b5b 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -2660,21 +2660,19 @@ bool Parser::isCompoundLiteralStorageClassSpecifier() const {
if (!getLangOpts().C23)
return false;
switch (Tok.getKind()) {
- case tok::kw_auto:
case tok::kw_constexpr:
- case tok::kw_extern:
case tok::kw_register:
case tok::kw_static:
+ case tok::kw___thread:
case tok::kw_thread_local:
case tok::kw__Thread_local:
- case tok::kw_typedef:
return true;
default:
return false;
}
}
-bool Parser::isCompoundLiteralTypeName() {
+bool Parser::isTypeIdInParensWithStorageClassSpecifiers() {
if (!isCompoundLiteralStorageClassSpecifier())
return false;
@@ -2686,52 +2684,11 @@ bool Parser::isCompoundLiteralTypeName() {
}
void Parser::ParseCompoundLiteralStorageClassSpecifiers(DeclSpec &DS) {
- DS.SetRangeStart(Tok.getLocation());
- const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy();
while (isCompoundLiteralStorageClassSpecifier()) {
- SourceLocation Loc = Tok.getLocation();
- const char *PrevSpec = nullptr;
- unsigned DiagID = 0;
- bool IsInvalid = false;
- switch (Tok.getKind()) {
- case tok::kw_typedef:
- IsInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_typedef, Loc,
- PrevSpec, DiagID, Policy);
- break;
- case tok::kw_extern:
- IsInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_extern, Loc,
- PrevSpec, DiagID, Policy);
- break;
- case tok::kw_static:
- IsInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_static, Loc,
- PrevSpec, DiagID, Policy);
- break;
- case tok::kw_auto:
- IsInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc,
- PrevSpec, DiagID, Policy);
- break;
- case tok::kw_register:
- IsInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_register, Loc,
- PrevSpec, DiagID, Policy);
- break;
- case tok::kw_thread_local:
- case tok::kw__Thread_local:
- IsInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS__Thread_local,
- Loc, PrevSpec, DiagID);
- break;
- case tok::kw_constexpr:
- IsInvalid = DS.SetConstexprSpec(ConstexprSpecKind::Constexpr, Loc,
- PrevSpec, DiagID);
- break;
- default:
- llvm_unreachable("unexpected compound literal storage class specifier");
- }
-
- if (IsInvalid)
- Diag(Loc, DiagID) << PrevSpec;
-
- DS.SetRangeEnd(Loc);
- ConsumeToken();
+ if (DS.getBeginLoc().isInvalid())
+ DS.SetRangeStart(Tok.getLocation());
+ ParseStorageClassSpecifier(DS,
+ StorageClassSpecifierContext::CompoundLiteral);
}
}
@@ -2852,7 +2809,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool StopIfCastExpr,
BridgeKeywordLoc, Ty.get(),
RParenLoc, SubExpr.get());
} else if (ExprType >= ParenParseOption::CompoundLiteral &&
- (isCompoundLiteralTypeName() ||
+ (isTypeIdInParensWithStorageClassSpecifiers() ||
isTypeIdInParens(isAmbiguousTypeId))) {
// Otherwise, this is a compound literal expression or cast expression.
@@ -2870,10 +2827,8 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool StopIfCastExpr,
}
DeclSpec CompoundDS(AttrFactory);
- if (isCompoundLiteralStorageClassSpecifier()) {
- ParseCompoundLiteralStorageClassSpecifiers(CompoundDS);
- CompoundDS.Finish(Actions, Actions.getASTContext().getPrintingPolicy());
- }
+ ParseCompoundLiteralStorageClassSpecifiers(CompoundDS);
+ CompoundDS.Finish(Actions, Actions.getASTContext().getPrintingPolicy());
DeclSpec DS(AttrFactory);
ParseSpecifierQualifierList(DS);
diff --git a/clang/test/AST/c23-compound-literal-print.c b/clang/test/AST/c23-compound-literal-print.c
index c8e4fb7d1e8e3..460f17db6a364 100644
--- a/clang/test/AST/c23-compound-literal-print.c
+++ b/clang/test/AST/c23-compound-literal-print.c
@@ -3,10 +3,10 @@
// RUN: %clang_cc1 -std=c23 -include-pch %t -ast-print -x c /dev/null | FileCheck %s
// CHECK-LABEL: int f1(void)
-// CHECK: return (constexpr int){1} + (static _Thread_local int){2} + (register int){3} + (constexpr const int){4};
+// CHECK: return (constexpr int){1} + (static _Thread_local int){2} + (register int){3} + (constexpr const int){4} + (static __thread int){5};
int f1(void) {
return (constexpr int){1} + (_Thread_local static int){2} + (register int){3} +
- (constexpr const int){4};
+ (constexpr const int){4} + (static __thread int){5};
}
// CHECK-LABEL: int f2(void)
diff --git a/clang/test/CodeGen/c23-compound-literal.c b/clang/test/CodeGen/c23-compound-literal.c
index 3f542021f5e21..875ffe55eece8 100644
--- a/clang/test/CodeGen/c23-compound-literal.c
+++ b/clang/test/CodeGen/c23-compound-literal.c
@@ -284,3 +284,11 @@ int f29(int a[f28(&(constexpr int){3})]) {
struct S f30(void) {
return (volatile struct S){19, 20};
}
+
+// CHECK-LABEL: define dso_local i32 @f31()
+// CHECK: [[ADDR:%.*]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @.compoundliteral
+// CHECK-NEXT: %[[VALUE:.*]] = load i32, ptr [[ADDR]], align 4
+// CHECK-NEXT: ret i32 %[[VALUE]]
+int f31(void) {
+ return (static __thread int){21};
+}
diff --git a/clang/test/Sema/c23-compound-literal.c b/clang/test/Sema/c23-compound-literal.c
index 1fe4210f036ba..f940e0ee51c26 100644
--- a/clang/test/Sema/c23-compound-literal.c
+++ b/clang/test/Sema/c23-compound-literal.c
@@ -11,6 +11,7 @@ void test1(void) {
(void)&(static int){42};
(void)(register int){0};
(void)(static thread_local int){1};
+ (void)(static __thread int){2};
(void)(constexpr struct S){1, 'a'};
(void)(static struct S){2, 'b'};
(void)(register struct S){3, 'c'};
@@ -315,11 +316,10 @@ void test21(void) {
}
void test22(void) {
- (void)(auto int){1}; // expected-error {{storage class specifier 'auto' is not permitted in a compound literal}}
- (void)(extern int){2}; // expected-error {{storage class specifier 'extern' is not permitted in a compound literal}}
- (void)(typedef int){3}; // expected-error {{storage class specifier 'typedef' is not permitted in a compound literal}}
+ (void)(auto int){1}; // expected-error {{expected expression}}
+ (void)(extern int){2}; // expected-error {{expected expression}}
+ (void)(typedef int){3}; // expected-error {{expected expression}}
(void)(__auto_type int){4}; // expected-error {{expected expression}}
- (void)(__thread int){5}; // expected-error {{expected expression}}
(void)(auto){1}; // expected-error {{expected expression}}
}
>From c4573785a61b7d7f7388a915e8f953ec7fdf6044 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk <oleksandr.tarasiuk at outlook.com>
Date: Tue, 1 Sep 2026 11:36:15 +0300
Subject: [PATCH 13/21] fix typo
---
clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 +-
clang/test/Sema/c23-compound-literal.c | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 0e5b33be551d9..fa4d124b4231b 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3179,7 +3179,7 @@ def err_c23_constexpr_init_type_mismatch : Error<
def err_c23_constexpr_pointer_not_null : Error<
"constexpr pointer initializer is not null">;
def err_register_compound_literal_file_scope : Error<
- "file-scope compound literal specifies 'register'">;
+ "file scope compound literal specifies 'register'">;
def err_thread_local_compound_literal_without_static : Error<
"compound literal with 'thread_local' storage duration at block scope must "
"also specify 'static'">;
diff --git a/clang/test/Sema/c23-compound-literal.c b/clang/test/Sema/c23-compound-literal.c
index f940e0ee51c26..424200b690956 100644
--- a/clang/test/Sema/c23-compound-literal.c
+++ b/clang/test/Sema/c23-compound-literal.c
@@ -45,7 +45,7 @@ void test5(void) {
(void)&(thread_local int){1}; // expected-error {{compound literal with 'thread_local' storage duration at block scope must also specify 'static'}}
}
-int *a1 = &(register int){42}; // expected-error {{file-scope compound literal specifies 'register'}}
+int *a1 = &(register int){42}; // expected-error {{file scope compound literal specifies 'register'}}
void test6(void) {
(void)(constexpr volatile int){1}; // expected-error {{constexpr compound literal cannot have type 'const volatile int'}}
@@ -263,7 +263,7 @@ inline int f19(int (*a(void))[sizeof((static int){1})]) { // expected-warning {{
inline typeof((static int){1}) f20(void) {
return 0;
}
-typeof((register int){1}) f21(void); // expected-error {{file-scope compound literal specifies 'register'}}
+typeof((register int){1}) f21(void); // expected-error {{file scope compound literal specifies 'register'}}
inline int f22(int a) __attribute__((enable_if((static int){1}, "enabled"))) { // expected-warning {{non-constant static local variable in inline function may be different in different files}} \
// expected-note {{use 'static' to give inline function 'f22' internal linkage}}
>From f3d616db890ee4fb156de2b763e0c07d72b2f886 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk <oleksandr.tarasiuk at outlook.com>
Date: Tue, 1 Sep 2026 11:46:26 +0300
Subject: [PATCH 14/21] combine tls alignment diagnostics
---
clang/include/clang/Basic/DiagnosticSemaKinds.td | 10 ++++------
clang/lib/Sema/SemaDecl.cpp | 7 ++++---
clang/lib/Sema/SemaDeclAttr.cpp | 5 +++--
clang/lib/Sema/SemaExpr.cpp | 4 ++--
4 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index fa4d124b4231b..eda496873ab0b 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3770,12 +3770,10 @@ def err_attr_codemodel_arg : Error<"code model '%0' is not supported on this tar
def err_aix_attr_unsupported : Error<"%0 attribute is not yet supported on AIX">;
-def err_tls_var_aligned_over_maximum : Error<
- "alignment (%0) of thread-local variable %1 is greater than the maximum supported "
- "alignment (%2) for a thread-local variable on this target">;
-def err_tls_compound_literal_aligned_over_maximum : Error<
- "alignment (%0) of thread-local compound literal is greater than the maximum "
- "supported alignment (%1) for thread-local storage on this target">;
+def err_tls_aligned_over_maximum : Error<
+ "alignment (%0) of thread-local %select{variable %3|compound literal}1 is "
+ "greater than the maximum supported alignment (%2) for "
+ "%select{a thread-local variable|thread-local storage}1 on this target">;
def err_only_annotate_after_access_spec : Error<
"access specifier can only have annotation attributes">;
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 5118966186fd1..10b3bada13272 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -15355,9 +15355,10 @@ void Sema::CheckThreadLocalForLargeAlignment(VarDecl *VD) {
if (!VD->hasDependentAlignment()) {
CharUnits MaxAlignChars = Context.toCharUnitsFromBits(MaxAlign);
if (Context.getDeclAlign(VD) > MaxAlignChars) {
- Diag(VD->getLocation(), diag::err_tls_var_aligned_over_maximum)
- << (unsigned)Context.getDeclAlign(VD).getQuantity() << VD
- << (unsigned)MaxAlignChars.getQuantity();
+ Diag(VD->getLocation(), diag::err_tls_aligned_over_maximum)
+ << (unsigned)Context.getDeclAlign(VD).getQuantity()
+ << /*IsCompoundLiteral=*/false
+ << (unsigned)MaxAlignChars.getQuantity() << VD;
}
}
}
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 6a67a8a124667..44dddcfdd768d 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -4894,8 +4894,9 @@ void Sema::AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E,
.getQuantity();
if (MaxTLSAlign && AlignVal > MaxTLSAlign &&
VD->getTLSKind() != VarDecl::TLS_None) {
- Diag(VD->getLocation(), diag::err_tls_var_aligned_over_maximum)
- << (unsigned)AlignVal << VD << MaxTLSAlign;
+ Diag(VD->getLocation(), diag::err_tls_aligned_over_maximum)
+ << (unsigned)AlignVal << /*IsCompoundLiteral=*/false << MaxTLSAlign
+ << VD;
return;
}
}
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index b3721f07a173e..4ba72b4acc34d 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -152,8 +152,8 @@ static bool checkThreadLocalCompoundLiteral(Sema &S, SourceLocation Loc,
if (TypeAlign <= MaxAlignChars)
return false;
- S.Diag(Loc, diag::err_tls_compound_literal_aligned_over_maximum)
- << (unsigned)TypeAlign.getQuantity()
+ S.Diag(Loc, diag::err_tls_aligned_over_maximum)
+ << (unsigned)TypeAlign.getQuantity() << /*IsCompoundLiteral=*/true
<< (unsigned)MaxAlignChars.getQuantity();
return true;
}
>From 516d7bb2e6ba134ae4e5e0c96381e0762f6b3c38 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk <oleksandr.tarasiuk at outlook.com>
Date: Tue, 1 Sep 2026 12:03:08 +0300
Subject: [PATCH 15/21] cleanup diagnostics
---
clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 --
clang/lib/Sema/SemaExpr.cpp | 2 +-
clang/test/Sema/c23-compound-literal.c | 8 ++++----
3 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index eda496873ab0b..b99b640b370b3 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3185,8 +3185,6 @@ def err_thread_local_compound_literal_without_static : Error<
"also specify 'static'">;
def err_compound_literal_invalid_storage_class : Error<
"storage class specifier '%0' is not permitted in a compound literal">;
-def err_constexpr_compound_literal_invalid_type : Error<
- "constexpr compound literal cannot have type %0">;
def err_compound_literal_initializer_not_constant : Error<
"initializer of compound literal must be a constant expression">;
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 4ba72b4acc34d..bb042abdcaeb8 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -7607,7 +7607,7 @@ ExprResult Sema::BuildCompoundLiteralExpr(
}
if (HasConstexpr &&
CheckConstexprType(ConstexprLoc, literalType,
- diag::err_constexpr_compound_literal_invalid_type))
+ diag::err_c23_constexpr_invalid_type))
return ExprError();
}
diff --git a/clang/test/Sema/c23-compound-literal.c b/clang/test/Sema/c23-compound-literal.c
index 424200b690956..e75ccf7662423 100644
--- a/clang/test/Sema/c23-compound-literal.c
+++ b/clang/test/Sema/c23-compound-literal.c
@@ -48,11 +48,11 @@ void test5(void) {
int *a1 = &(register int){42}; // expected-error {{file scope compound literal specifies 'register'}}
void test6(void) {
- (void)(constexpr volatile int){1}; // expected-error {{constexpr compound literal cannot have type 'const volatile int'}}
- (void)(constexpr _Atomic int){1}; // expected-error {{constexpr compound literal cannot have type 'const _Atomic(int)'}}
+ (void)(constexpr volatile int){1}; // expected-error {{constexpr variable cannot have type 'const volatile int'}}
+ (void)(constexpr _Atomic int){1}; // expected-error {{constexpr variable cannot have type 'const _Atomic(int)'}}
int c;
- (void)(constexpr int[c]){0}; // expected-error {{constexpr compound literal cannot have type 'const int[c]'}}
+ (void)(constexpr int[c]){0}; // expected-error {{constexpr variable cannot have type 'const int[c]'}}
}
void test7(void) {
@@ -187,7 +187,7 @@ struct S8 {
int *restrict a;
};
void test16(void) {
- (void)(constexpr struct S8){0}; // expected-error {{constexpr compound literal cannot have type 'int *restrict'}}
+ (void)(constexpr struct S8){0}; // expected-error {{constexpr variable cannot have type 'int *restrict'}}
}
void test17(void) {
>From a97c037e1939d517f3c041b9744dc42b6fd83617 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk <oleksandr.tarasiuk at outlook.com>
Date: Tue, 1 Sep 2026 12:11:43 +0300
Subject: [PATCH 16/21] add additional tests
---
clang/test/Parser/c23-compound-literal.c | 32 ++++++++++++++++++++++++
1 file changed, 32 insertions(+)
create mode 100644 clang/test/Parser/c23-compound-literal.c
diff --git a/clang/test/Parser/c23-compound-literal.c b/clang/test/Parser/c23-compound-literal.c
new file mode 100644
index 0000000000000..3415bba7454e6
--- /dev/null
+++ b/clang/test/Parser/c23-compound-literal.c
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -std=c17 -fsyntax-only -verify=c17 %s
+// RUN: %clang_cc1 -x c++ -std=c++23 -fsyntax-only -verify=cxx %s
+
+void t1(void) {
+ (void)(static int){1}; // c17-error {{expected expression}} \
+ // cxx-error {{type name does not allow storage class to be specified}}
+}
+
+void t2(void) {
+ (void)(register int){1}; // c17-error {{expected expression}} \
+ // cxx-error {{type name does not allow storage class to be specified}}
+}
+
+void t3(void) {
+ (void)(thread_local int){1}; // c17-error {{use of undeclared identifier 'thread_local'}} \
+ // cxx-error {{type name does not allow storage class to be specified}}
+}
+
+void t4(void) {
+ (void)(_Thread_local int){1}; // c17-error {{expected expression}} \
+ // cxx-error {{type name does not allow storage class to be specified}}
+}
+
+void t5(void) {
+ (void)(__thread int){1}; // c17-error {{expected expression}} \
+ // cxx-error {{type name does not allow storage class to be specified}}
+}
+
+void t6(void) {
+ (void)(constexpr int){1}; // c17-error {{use of undeclared identifier 'constexpr'}} \
+ // cxx-error {{type name does not allow constexpr specifier to be specified}}
+}
>From e176138a4ec97927e9c9c428c73556328455df4a Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk <oleksandr.tarasiuk at outlook.com>
Date: Tue, 1 Sep 2026 13:32:32 +0300
Subject: [PATCH 17/21] clarify thread-local compound literal constant
evaluation
---
clang/lib/AST/Expr.cpp | 1 +
clang/lib/AST/ExprConstant.cpp | 9 +--------
2 files changed, 2 insertions(+), 8 deletions(-)
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 577a101714efd..8dbc2816c4576 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -3417,6 +3417,7 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef,
// "struct x {int x;} x = (struct x) {};".
// FIXME: This accepts other cases it shouldn't!
const auto *CLE = cast<CompoundLiteralExpr>(this);
+ // A constant initializer cannot access a thread-local lvalue.
if (CLE->hasThreadStorage()) {
if (Culprit)
*Culprit = this;
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index d13110bf1abb5..988f8818e7a70 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -4878,14 +4878,6 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
assert(BaseVal && "got reference to unevaluated temporary");
} else if (const CompoundLiteralExpr *CLE =
dyn_cast_or_null<CompoundLiteralExpr>(Base)) {
- if (CLE->hasThreadStorage()) {
- if (IsAccess) {
- Info.FFDiag(E);
- return CompleteObject();
- }
- return CompleteObject(LVal.getLValueBase(), nullptr, BaseType);
- }
-
// According to GCC info page:
//
// 6.28 Compound Literals
@@ -9761,6 +9753,7 @@ bool
LValueExprEvaluator::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) {
assert((!Info.getLangOpts().CPlusPlus || E->isFileScope()) &&
"lvalue compound literal in c++?");
+ // A thread-local lvalue cannot be the result of constant evaluation.
if (E->hasThreadStorage()) {
Info.FFDiag(E);
return false;
>From 94df8bdb826f1df4bfc6cc46c0ab68d4b07453e8 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk <oleksandr.tarasiuk at outlook.com>
Date: Tue, 1 Sep 2026 17:23:38 +0300
Subject: [PATCH 18/21] remove ParameterList kind
---
clang/include/clang/AST/Expr.h | 4 +-
clang/lib/CodeGen/CGExpr.cpp | 12 ++---
clang/lib/Parse/ParseDecl.cpp | 2 +
clang/lib/Sema/SemaExpr.cpp | 51 +++++++++++--------
clang/test/CodeGenObjC/c23-compound-literal.m | 18 +++++++
5 files changed, 55 insertions(+), 32 deletions(-)
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 133171c49ff63..f6790652f2f59 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -3610,7 +3610,7 @@ class MemberExpr final
///
class CompoundLiteralExpr : public Expr {
public:
- enum class ScopeKind { Block, File, ParameterList };
+ enum class ScopeKind { Block, File };
private:
/// LParenLoc - If non-null, this is the location of the left paren in a
@@ -3620,7 +3620,7 @@ class CompoundLiteralExpr : public Expr {
/// The type as written. This can be an incomplete array type, in
/// which case the actual expression type will be different.
- llvm::PointerIntPair<TypeSourceInfo *, 2, ScopeKind> TInfoAndScope;
+ llvm::PointerIntPair<TypeSourceInfo *, 1, ScopeKind> TInfoAndScope;
Stmt *Init;
/// Value of constant literals with static storage duration.
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index bfd21925691f3..1d062c1ce14e9 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -6023,14 +6023,10 @@ CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr *E) {
// Block-scope compound literals are destroyed at the end of the enclosing
// scope in C.
if (!getLangOpts().CPlusPlus) {
- if (QualType::DestructionKind DtorKind = E->getType().isDestructedType()) {
- if (E->getScopeKind() == CompoundLiteralExpr::ScopeKind::ParameterList)
- pushDestroy(DtorKind, DeclPtr, E->getType());
- else
- pushLifetimeExtendedDestroy(getCleanupKind(DtorKind), DeclPtr,
- E->getType(), getDestroyer(DtorKind),
- DtorKind & EHCleanup);
- }
+ if (QualType::DestructionKind DtorKind = E->getType().isDestructedType())
+ pushLifetimeExtendedDestroy(getCleanupKind(DtorKind), DeclPtr,
+ E->getType(), getDestroyer(DtorKind),
+ DtorKind & EHCleanup);
}
return Result;
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 8389aae8e0e23..49ec3d206570c 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -8009,6 +8009,8 @@ void Parser::ParseBracketDeclarator(Declarator &D) {
EnterExpressionEvaluationContext Unevaluated(
Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
NumElements = ParseAssignmentExpression();
+ if (NumElements.isUsable())
+ NumElements = Actions.MaybeCreateExprWithCleanups(NumElements);
}
} else {
if (StaticLoc.isValid()) {
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index bb042abdcaeb8..ec3bbacf377d0 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -7581,7 +7581,6 @@ ExprResult Sema::BuildCompoundLiteralExpr(
bool HasThreadStorage = TSC != TSCS_unspecified;
bool HasConstexpr = ConstexprKind == ConstexprSpecKind::Constexpr;
- bool IsPrototypeScope = PrototypeScope;
bool IsFunctionDeclarationScope =
PrototypeScope && PrototypeScope->isFunctionDeclarationScope();
bool IsFileScope = !CurContext->isFunctionOrMethod() &&
@@ -7713,9 +7712,8 @@ ExprResult Sema::BuildCompoundLiteralExpr(
? VK_PRValue
: VK_LValue;
CompoundLiteralExpr::ScopeKind Scope =
- IsFileScope ? CompoundLiteralExpr::ScopeKind::File
- : IsPrototypeScope ? CompoundLiteralExpr::ScopeKind::ParameterList
- : CompoundLiteralExpr::ScopeKind::Block;
+ IsFileScope ? CompoundLiteralExpr::ScopeKind::File
+ : CompoundLiteralExpr::ScopeKind::Block;
bool HasGlobalStorage =
IsFileScope || (getLangOpts().C23 && (HasStatic || HasThreadStorage));
@@ -7772,31 +7770,40 @@ ExprResult Sema::BuildCompoundLiteralExpr(
}
if (HasStatic && !literalType.isConstQualified()) {
- if (!IsPrototypeScope) {
+ if (PrototypeScope) {
+ if (IsFunctionDeclarationScope &&
+ DelayedDiagnostics.shouldDelayDiagnostics())
+ DelayedDiagnostics.add(
+ sema::DelayedDiagnostic::makeForbiddenStatic(StorageClassLoc));
+ } else {
DiagnoseStaticInInline(StorageClassLoc, getCurFunctionDecl());
- } else if (IsFunctionDeclarationScope &&
- DelayedDiagnostics.shouldDelayDiagnostics()) {
- DelayedDiagnostics.add(
- sema::DelayedDiagnostic::makeForbiddenStatic(StorageClassLoc));
}
}
- if (!HasGlobalStorage && !IsPrototypeScope && !getLangOpts().CPlusPlus) {
+ if (!HasGlobalStorage && !getLangOpts().CPlusPlus) {
// Compound literals that have automatic storage duration are destroyed at
// the end of the scope in C; in C++, they're just temporaries.
- // Emit diagnostics if it is or contains a C union type that is non-trivial
- // to destruct.
- if (E->getType().hasNonTrivialToPrimitiveDestructCUnion())
- checkNonTrivialCUnion(E->getType(), E->getExprLoc(),
- NonTrivialCUnionContext::CompoundLiteral,
- NTCUK_Destruct);
-
- // Diagnose jumps that enter or exit the lifetime of the compound literal.
- if (literalType.isDestructedType()) {
- Cleanup.setExprNeedsCleanups(true);
- ExprCleanupObjects.push_back(E);
- getCurFunction()->setHasBranchProtectedScope();
+ if (PrototypeScope) {
+ if (literalType.isDestructedType()) {
+ Cleanup.setExprNeedsCleanups(true);
+ ExprCleanupObjects.push_back(E);
+ }
+ } else {
+ // Emit diagnostics if it is or contains a C union type that is
+ // non-trivial to destruct.
+ if (E->getType().hasNonTrivialToPrimitiveDestructCUnion())
+ checkNonTrivialCUnion(E->getType(), E->getExprLoc(),
+ NonTrivialCUnionContext::CompoundLiteral,
+ NTCUK_Destruct);
+
+ // Diagnose jumps that enter or exit the lifetime of the compound
+ // literal.
+ if (literalType.isDestructedType()) {
+ Cleanup.setExprNeedsCleanups(true);
+ ExprCleanupObjects.push_back(E);
+ getCurFunction()->setHasBranchProtectedScope();
+ }
}
}
diff --git a/clang/test/CodeGenObjC/c23-compound-literal.m b/clang/test/CodeGenObjC/c23-compound-literal.m
index 245284cb23017..c693071b0f213 100644
--- a/clang/test/CodeGenObjC/c23-compound-literal.m
+++ b/clang/test/CodeGenObjC/c23-compound-literal.m
@@ -10,6 +10,7 @@
// CHECK: store ptr null, ptr %{{.*}}, align 8
// CHECK: %[[CALL:.*]] = call i32 @f1(ptr noundef %.compoundliteral)
// CHECK-NEXT: zext i32 %[[CALL]] to i64
+// CHECK-NOT: call void @__destructor_8_s0(ptr %.compoundliteral)
// CHECK: %[[RESULT:.*]] = load i32, ptr %{{.*}}, align 4
// CHECK-NEXT: call void @__destructor_8_s0(ptr %.compoundliteral)
// CHECK-NEXT: ret i32 %[[RESULT]]
@@ -17,3 +18,20 @@
int f2(int a[f1(&(constexpr S){.a = 0})]) {
return a[0];
}
+
+// CHECK-LABEL: define i32 @f3(
+// CHECK: %.compoundliteral = alloca %struct.S, align 8
+// CHECK: br i1 %{{.*}}, label %[[RETURN0:.*]], label %[[CONTINUE:.*]]
+// CHECK: [[RETURN0]]:
+// CHECK: br label %[[CLEANUP:.*]]
+// CHECK: [[CONTINUE]]:
+// CHECK: br label %[[CLEANUP]]
+// CHECK: [[CLEANUP]]:
+// CHECK-NEXT: call void @__destructor_8_s0(ptr %.compoundliteral)
+// CHECK-NEXT: %[[RESULT:.*]] = load i32, ptr %{{.*}}, align 4
+// CHECK-NEXT: ret i32 %[[RESULT]]
+int f3(int c, int a[f1(&(constexpr S){.a = 0})]) {
+ if (c)
+ return a[0];
+ return a[1];
+}
>From 3aed63a93ebed9a9584225f574a4bd0432f797be Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk <oleksandr.tarasiuk at outlook.com>
Date: Tue, 1 Sep 2026 17:42:50 +0300
Subject: [PATCH 19/21] avoid diagnosing register compound literal array
---
clang/lib/Sema/SemaExpr.cpp | 103 ++++++++++++-------------
clang/test/Sema/c23-compound-literal.c | 5 +-
2 files changed, 51 insertions(+), 57 deletions(-)
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index ec3bbacf377d0..890cb1598e526 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -554,54 +554,6 @@ SourceRange Sema::getExprRange(Expr *E) const {
// Standard Promotions and Conversions
//===----------------------------------------------------------------------===//
-namespace {
-enum {
- AO_Bit_Field = 0,
- AO_Vector_Element = 1,
- AO_Property_Expansion = 2,
- AO_Register_Variable = 3,
- AO_Matrix_Element = 4,
- AO_Register_Compound_Literal = 5,
- AO_No_Error = 6
-};
-}
-
-using PrimaryObject = llvm::PointerUnion<ValueDecl *, CompoundLiteralExpr *>;
-
-static PrimaryObject getPrimaryObject(Expr *E) {
- E = E->IgnoreParens();
- switch (E->getStmtClass()) {
- case Stmt::DeclRefExprClass:
- return cast<DeclRefExpr>(E)->getDecl();
- case Stmt::CompoundLiteralExprClass:
- return cast<CompoundLiteralExpr>(E);
- case Stmt::MemberExprClass:
- if (cast<MemberExpr>(E)->isArrow())
- return {};
- return getPrimaryObject(cast<MemberExpr>(E)->getBase());
- case Stmt::ArraySubscriptExprClass: {
- Expr *Base = cast<ArraySubscriptExpr>(E)->getBase()->IgnoreParens();
- if (auto *ICE = dyn_cast<ImplicitCastExpr>(Base);
- ICE && ICE->getSubExpr()->getType()->isArrayType())
- return getPrimaryObject(ICE->getSubExpr());
- return {};
- }
- case Stmt::UnaryOperatorClass: {
- UnaryOperator *UO = cast<UnaryOperator>(E);
- if (UO->getOpcode() == UO_Real || UO->getOpcode() == UO_Imag ||
- UO->getOpcode() == UO_Extension)
- return getPrimaryObject(UO->getSubExpr());
- return {};
- }
- case Stmt::ImplicitCastExprClass:
- return getPrimaryObject(cast<ImplicitCastExpr>(E)->getSubExpr());
- case Stmt::CXXUuidofExprClass:
- return cast<CXXUuidofExpr>(E)->getGuidDecl();
- default:
- return {};
- }
-}
-
/// DefaultFunctionArrayConversion (C99 6.3.2.1p3, C99 6.3.2.1p4).
ExprResult Sema::DefaultFunctionArrayConversion(Expr *E, bool Diagnose) {
// Handle any placeholder expressions which made it here.
@@ -635,13 +587,6 @@ ExprResult Sema::DefaultFunctionArrayConversion(Expr *E, bool Diagnose) {
// T" can be converted to an rvalue of type "pointer to T".
//
if (getLangOpts().C99 || getLangOpts().CPlusPlus || E->isLValue()) {
- if (!getLangOpts().CPlusPlus) {
- auto *CLE = getPrimaryObject(E).dyn_cast<CompoundLiteralExpr *>();
- if (CLE && CLE->getStorageClass() == SC_Register)
- return Diag(E->getExprLoc(), diag::err_typecheck_address_of)
- << AO_Register_Compound_Literal << CLE->getSourceRange();
- }
-
ExprResult Res = ImpCastExprToType(E, Context.getArrayDecayedType(Ty),
CK_ArrayToPointerDecay);
if (Res.isInvalid())
@@ -15070,6 +15015,54 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op,
}
}
+namespace {
+enum {
+ AO_Bit_Field = 0,
+ AO_Vector_Element = 1,
+ AO_Property_Expansion = 2,
+ AO_Register_Variable = 3,
+ AO_Matrix_Element = 4,
+ AO_Register_Compound_Literal = 5,
+ AO_No_Error = 6
+};
+}
+
+using PrimaryObject = llvm::PointerUnion<ValueDecl *, CompoundLiteralExpr *>;
+
+static PrimaryObject getPrimaryObject(Expr *E) {
+ E = E->IgnoreParens();
+ switch (E->getStmtClass()) {
+ case Stmt::DeclRefExprClass:
+ return cast<DeclRefExpr>(E)->getDecl();
+ case Stmt::CompoundLiteralExprClass:
+ return cast<CompoundLiteralExpr>(E);
+ case Stmt::MemberExprClass:
+ if (cast<MemberExpr>(E)->isArrow())
+ return {};
+ return getPrimaryObject(cast<MemberExpr>(E)->getBase());
+ case Stmt::ArraySubscriptExprClass: {
+ Expr *Base = cast<ArraySubscriptExpr>(E)->getBase()->IgnoreParens();
+ if (auto *ICE = dyn_cast<ImplicitCastExpr>(Base);
+ ICE && ICE->getSubExpr()->getType()->isArrayType())
+ return getPrimaryObject(ICE->getSubExpr());
+ return {};
+ }
+ case Stmt::UnaryOperatorClass: {
+ UnaryOperator *UO = cast<UnaryOperator>(E);
+ if (UO->getOpcode() == UO_Real || UO->getOpcode() == UO_Imag ||
+ UO->getOpcode() == UO_Extension)
+ return getPrimaryObject(UO->getSubExpr());
+ return {};
+ }
+ case Stmt::ImplicitCastExprClass:
+ return getPrimaryObject(cast<ImplicitCastExpr>(E)->getSubExpr());
+ case Stmt::CXXUuidofExprClass:
+ return cast<CXXUuidofExpr>(E)->getGuidDecl();
+ default:
+ return {};
+ }
+}
+
/// Diagnose invalid operand for address of operations.
///
/// \param Type The type of operand which cannot have its address taken.
diff --git a/clang/test/Sema/c23-compound-literal.c b/clang/test/Sema/c23-compound-literal.c
index e75ccf7662423..2a7c49121af72 100644
--- a/clang/test/Sema/c23-compound-literal.c
+++ b/clang/test/Sema/c23-compound-literal.c
@@ -87,15 +87,16 @@ void test8(void) {
void test9(void) {
int *a = &(register int){1}; // expected-error {{address of register compound literal requested}}
- int *b = (register int[1]){1}; // expected-error {{address of register compound literal requested}}
+ int *b = (register int[1]){1};
struct S2 { int a; };
int *c = &(register struct S2){1}.a; // expected-error {{address of register compound literal requested}}
double *d = &__real__ (register _Complex double){1}; // expected-error {{address of register compound literal requested}}
double *e = &__imag__ (register _Complex double){1}; // expected-error {{address of register compound literal requested}}
int *f = &_Generic(0, int: (register int){1}); // expected-error {{address of register compound literal requested}}
- int *g = _Generic(0, int: (register int[1]){1}); // expected-error {{address of register compound literal requested}}
+ int *g = _Generic(0, int: (register int[1]){1});
int *h = &_Generic(0, int: (register struct S2){1}).a; // expected-error {{address of register compound literal requested}}
int *i = &__extension__ (register int){1}; // expected-error {{address of register compound literal requested}}
+ int (*j)[1] = &(register int[1]){1}; // expected-error {{address of register compound literal requested}}
}
int a5[1];
>From 0b29d9a7584f8dfbe4275159b7cf3f282dcf6b1b Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk <oleksandr.tarasiuk at outlook.com>
Date: Fri, 4 Sep 2026 08:49:16 +0300
Subject: [PATCH 20/21] add additional obj-c test
---
clang/test/Sema/c23-compound-literal.m | 1 +
1 file changed, 1 insertion(+)
diff --git a/clang/test/Sema/c23-compound-literal.m b/clang/test/Sema/c23-compound-literal.m
index 142e5a49499eb..1ddc5d6f583eb 100644
--- a/clang/test/Sema/c23-compound-literal.m
+++ b/clang/test/Sema/c23-compound-literal.m
@@ -6,6 +6,7 @@
void test1(void) {
(void)(thread_local static __unsafe_unretained id){0};
+ (void)(thread_local static Class){0};
(void)(thread_local static id){0}; // expected-error {{thread-local variable has non-trivial ownership: type is '__strong id'}}
(void)(thread_local static S){0}; // expected-error {{type of thread-local variable has non-trivial destruction}}
}
>From c50c8b23dac63f6bfeb15baf169aff4ec0d651e1 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk <oleksandr.tarasiuk at outlook.com>
Date: Sun, 13 Sep 2026 22:18:00 +0300
Subject: [PATCH 21/21] revert unrelated formatting changes
---
clang/lib/CodeGen/CGExpr.cpp | 443 ++++---
clang/lib/Sema/SemaExpr.cpp | 2418 ++++++++++++++++------------------
2 files changed, 1397 insertions(+), 1464 deletions(-)
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 4aaeee4b7aeb0..961e8b20527fe 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -279,7 +279,8 @@ void CodeGenFunction::EmitIgnoredExpr(const Expr *E) {
/// can have any type. The result is returned as an RValue struct.
/// If this is an aggregate expression, AggSlot indicates where the
/// result should be returned.
-RValue CodeGenFunction::EmitAnyExpr(const Expr *E, AggValueSlot aggSlot,
+RValue CodeGenFunction::EmitAnyExpr(const Expr *E,
+ AggValueSlot aggSlot,
bool ignoreResult) {
switch (getEvaluationKind(E->getType())) {
case TEK_Scalar:
@@ -307,8 +308,10 @@ RValue CodeGenFunction::EmitAnyExprToTemp(const Expr *E) {
/// EmitAnyExprToMem - Evaluate an expression into a given memory
/// location.
-void CodeGenFunction::EmitAnyExprToMem(const Expr *E, Address Location,
- Qualifiers Quals, bool IsInit) {
+void CodeGenFunction::EmitAnyExprToMem(const Expr *E,
+ Address Location,
+ Qualifiers Quals,
+ bool IsInit) {
// FIXME: This function should take an LValue as an argument.
switch (getEvaluationKind(E->getType())) {
case TEK_Complex:
@@ -358,9 +361,9 @@ void CodeGenFunction::EmitInitializationToLValue(
llvm_unreachable("bad evaluation kind");
}
-static void pushTemporaryCleanup(CodeGenFunction &CGF,
- const MaterializeTemporaryExpr *M,
- const Expr *E, Address ReferenceTemporary) {
+static void
+pushTemporaryCleanup(CodeGenFunction &CGF, const MaterializeTemporaryExpr *M,
+ const Expr *E, Address ReferenceTemporary) {
// Objective-C++ ARC:
// If we are binding a reference to a temporary that has ownership, we
// need to perform retain/release operations on the temporary.
@@ -407,12 +410,13 @@ static void pushTemporaryCleanup(CodeGenFunction &CGF,
Destroy = &CodeGenFunction::destroyARCWeak;
}
if (Duration == SD_FullExpression)
- CGF.pushDestroy(CleanupKind, ReferenceTemporary, M->getType(),
- *Destroy, CleanupKind & EHCleanup);
+ CGF.pushDestroy(CleanupKind, ReferenceTemporary,
+ M->getType(), *Destroy,
+ CleanupKind & EHCleanup);
else
CGF.pushLifetimeExtendedDestroy(CleanupKind, ReferenceTemporary,
- M->getType(), *Destroy,
- CleanupKind & EHCleanup);
+ M->getType(),
+ *Destroy, CleanupKind & EHCleanup);
return;
case SD_Dynamic:
@@ -511,8 +515,8 @@ static RawAddress createReferenceTemporary(CodeGenFunction &CGF,
llvm_unreachable("unknown storage duration");
}
-LValue CodeGenFunction::EmitMaterializeTemporaryExpr(
- const MaterializeTemporaryExpr *M) {
+LValue CodeGenFunction::
+EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
const Expr *E = M->getSubExpr();
assert((!M->getExtendingDecl() || !isa<VarDecl>(M->getExtendingDecl()) ||
@@ -540,17 +544,17 @@ LValue CodeGenFunction::EmitMaterializeTemporaryExpr(
Var->setInitializer(CGM.EmitNullConstant(E->getType()));
}
- LValue RefTempDst =
- MakeAddrLValue(Object, M->getType(), AlignmentSource::Decl);
+ LValue RefTempDst = MakeAddrLValue(Object, M->getType(),
+ AlignmentSource::Decl);
switch (getEvaluationKind(E->getType())) {
- default:
- llvm_unreachable("expected scalar or aggregate expression");
+ default: llvm_unreachable("expected scalar or aggregate expression");
case TEK_Scalar:
EmitScalarInit(E, M->getExtendingDecl(), RefTempDst, false);
break;
case TEK_Aggregate: {
- EmitAggExpr(E, AggValueSlot::forAddr(Object, E->getType().getQualifiers(),
+ EmitAggExpr(E, AggValueSlot::forAddr(Object,
+ E->getType().getQualifiers(),
AggValueSlot::IsDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
AggValueSlot::IsNotAliased,
@@ -650,7 +654,7 @@ LValue CodeGenFunction::EmitMaterializeTemporaryExpr(
default:
break;
}
- EmitAnyExprToMem(E, Object, Qualifiers(), /*IsInit*/ true);
+ EmitAnyExprToMem(E, Object, Qualifiers(), /*IsInit*/true);
}
pushTemporaryCleanup(*this, M, E, Object);
@@ -664,7 +668,7 @@ LValue CodeGenFunction::EmitMaterializeTemporaryExpr(
GetAddressOfBaseClass(Object, Adjustment.DerivedToBase.DerivedClass,
Adjustment.DerivedToBase.BasePath->path_begin(),
Adjustment.DerivedToBase.BasePath->path_end(),
- /*NullCheckValue=*/false, E->getExprLoc());
+ /*NullCheckValue=*/ false, E->getExprLoc());
break;
case SubobjectAdjustment::FieldAdjustment: {
@@ -688,7 +692,8 @@ LValue CodeGenFunction::EmitMaterializeTemporaryExpr(
return MakeAddrLValue(Object, M->getType(), AlignmentSource::Decl);
}
-RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr *E) {
+RValue
+CodeGenFunction::EmitReferenceBindingToExpr(const Expr *E) {
// Emit the expression as an lvalue.
LValue LV = EmitLValue(E);
assert(LV.isSimple());
@@ -707,6 +712,7 @@ RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr *E) {
return RValue::get(Value);
}
+
/// getAccessedFieldNo - Given an encoded value and a result number, return the
/// input field number being accessed.
unsigned CodeGenFunction::getAccessedFieldNo(unsigned Idx,
@@ -915,9 +921,9 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
llvm::Type *VPtrTy = llvm::PointerType::get(getLLVMContext(), 0);
Address VPtrAddr(Ptr, IntPtrTy, getPointerAlign());
- llvm::Value *VPtrVal =
- GetVTablePtr(VPtrAddr, VPtrTy, Ty->getAsCXXRecordDecl(),
- VTableAuthMode::UnsafeUbsanStrip);
+ llvm::Value *VPtrVal = GetVTablePtr(VPtrAddr, VPtrTy,
+ Ty->getAsCXXRecordDecl(),
+ VTableAuthMode::UnsafeUbsanStrip);
VPtrVal = Builder.CreateBitOrPointerCast(VPtrVal, IntPtrTy);
llvm::Value *Hash =
@@ -927,11 +933,12 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
// Look the hash up in our cache.
const int CacheSize = 128;
llvm::Type *HashTable = llvm::ArrayType::get(IntPtrTy, CacheSize);
- llvm::Value *Cache =
- CGM.CreateRuntimeVariable(HashTable, "__ubsan_vptr_type_cache");
- llvm::Value *Slot = Builder.CreateAnd(
- Hash, llvm::ConstantInt::get(IntPtrTy, CacheSize - 1));
- llvm::Value *Indices[] = {Builder.getInt32(0), Slot};
+ llvm::Value *Cache = CGM.CreateRuntimeVariable(HashTable,
+ "__ubsan_vptr_type_cache");
+ llvm::Value *Slot = Builder.CreateAnd(Hash,
+ llvm::ConstantInt::get(IntPtrTy,
+ CacheSize-1));
+ llvm::Value *Indices[] = { Builder.getInt32(0), Slot };
llvm::Value *CacheVal = Builder.CreateAlignedLoad(
IntPtrTy, Builder.CreateInBoundsGEP(HashTable, Cache, Indices),
getPointerAlign());
@@ -942,10 +949,12 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
// diagnostic.
llvm::Value *EqualHash = Builder.CreateICmpEQ(CacheVal, Hash);
llvm::Constant *StaticData[] = {
- EmitCheckSourceLocation(Loc), EmitCheckTypeDescriptor(Ty),
- CGM.GetAddrOfRTTIDescriptor(Ty.getUnqualifiedType()),
- llvm::ConstantInt::get(Int8Ty, TCK)};
- llvm::Value *DynamicData[] = {Ptr, Hash};
+ EmitCheckSourceLocation(Loc),
+ EmitCheckTypeDescriptor(Ty),
+ CGM.GetAddrOfRTTIDescriptor(Ty.getUnqualifiedType()),
+ llvm::ConstantInt::get(Int8Ty, TCK)
+ };
+ llvm::Value *DynamicData[] = { Ptr, Hash };
EmitCheck(std::make_pair(EqualHash, SanitizerKind::SO_Vptr),
SanitizerHandler::DynamicTypeCacheMiss, StaticData,
DynamicData);
@@ -1004,9 +1013,11 @@ llvm::Value *CodeGenFunction::LoadPassedObjectSize(const Expr *E,
/// If Base is known to point to the start of an array, return the length of
/// that array. Return 0 if the length cannot be determined.
-static llvm::Value *getArrayIndexingBound(
- CodeGenFunction &CGF, const Expr *Base, QualType &IndexedType,
- LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel) {
+static llvm::Value *getArrayIndexingBound(CodeGenFunction &CGF,
+ const Expr *Base,
+ QualType &IndexedType,
+ LangOptions::StrictFlexArraysLevelKind
+ StrictFlexArraysLevel) {
// For the vector indexing extension, the bound is the number of elements.
if (const VectorType *VT = Base->getType()->getAs<VectorType>()) {
IndexedType = Base->getType();
@@ -1363,9 +1374,9 @@ void CodeGenFunction::EmitAllocToken(llvm::CallBase *CB, const CallExpr *E) {
CB->setMetadata(llvm::LLVMContext::MD_alloc_token, MDN);
}
-CodeGenFunction::ComplexPairTy
-CodeGenFunction::EmitComplexPrePostIncDec(const UnaryOperator *E, LValue LV,
- bool isInc, bool isPre) {
+CodeGenFunction::ComplexPairTy CodeGenFunction::
+EmitComplexPrePostIncDec(const UnaryOperator *E, LValue LV,
+ bool isInc, bool isPre) {
ComplexPairTy InVal = EmitLoadOfComplex(LV, E->getExprLoc());
llvm::Value *NextVal;
@@ -1491,10 +1502,8 @@ static Address EmitPointerWithAlignment(const Expr *E, LValueBaseInfo *BaseInfo,
TBAAAccessInfo InnerTBAAInfo;
Address Addr = CGF.EmitPointerWithAlignment(
CE->getSubExpr(), &InnerBaseInfo, &InnerTBAAInfo, IsKnownNonNull);
- if (BaseInfo)
- *BaseInfo = InnerBaseInfo;
- if (TBAAInfo)
- *TBAAInfo = InnerTBAAInfo;
+ if (BaseInfo) *BaseInfo = InnerBaseInfo;
+ if (TBAAInfo) *TBAAInfo = InnerTBAAInfo;
if (isa<ExplicitCastExpr>(CE)) {
LValueBaseInfo TargetTypeBaseInfo;
@@ -1567,10 +1576,8 @@ static Address EmitPointerWithAlignment(const Expr *E, LValueBaseInfo *BaseInfo,
if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
if (UO->getOpcode() == UO_AddrOf) {
LValue LV = CGF.EmitLValue(UO->getSubExpr(), IsKnownNonNull);
- if (BaseInfo)
- *BaseInfo = LV.getBaseInfo();
- if (TBAAInfo)
- *TBAAInfo = LV.getTBAAInfo();
+ if (BaseInfo) *BaseInfo = LV.getBaseInfo();
+ if (TBAAInfo) *TBAAInfo = LV.getTBAAInfo();
return LV.getAddress();
}
}
@@ -1584,10 +1591,8 @@ static Address EmitPointerWithAlignment(const Expr *E, LValueBaseInfo *BaseInfo,
case Builtin::BI__addressof:
case Builtin::BI__builtin_addressof: {
LValue LV = CGF.EmitLValue(Call->getArg(0), IsKnownNonNull);
- if (BaseInfo)
- *BaseInfo = LV.getBaseInfo();
- if (TBAAInfo)
- *TBAAInfo = LV.getTBAAInfo();
+ if (BaseInfo) *BaseInfo = LV.getBaseInfo();
+ if (TBAAInfo) *TBAAInfo = LV.getTBAAInfo();
return LV.getAddress();
}
}
@@ -1633,7 +1638,7 @@ RValue CodeGenFunction::GetUndefRValue(QualType Ty) {
switch (getEvaluationKind(Ty)) {
case TEK_Complex: {
llvm::Type *EltTy =
- ConvertType(Ty->castAs<ComplexType>()->getElementType());
+ ConvertType(Ty->castAs<ComplexType>()->getElementType());
llvm::Value *U = llvm::UndefValue::get(EltTy);
return RValue::getComplex(std::make_pair(U, U));
}
@@ -1652,12 +1657,14 @@ RValue CodeGenFunction::GetUndefRValue(QualType Ty) {
llvm_unreachable("bad evaluation kind");
}
-RValue CodeGenFunction::EmitUnsupportedRValue(const Expr *E, const char *Name) {
+RValue CodeGenFunction::EmitUnsupportedRValue(const Expr *E,
+ const char *Name) {
ErrorUnsupported(E, Name);
return GetUndefRValue(E->getType());
}
-LValue CodeGenFunction::EmitUnsupportedLValue(const Expr *E, const char *Name) {
+LValue CodeGenFunction::EmitUnsupportedLValue(const Expr *E,
+ const char *Name) {
ErrorUnsupported(E, Name);
llvm::Type *ElTy = ConvertType(E->getType());
llvm::Type *Ty = DefaultPtrTy;
@@ -1691,7 +1698,7 @@ bool CodeGenFunction::IsWrappedCXXThis(const Expr *Obj) {
LValue CodeGenFunction::EmitCheckedLValue(const Expr *E, TypeCheckKind TCK) {
LValue LV;
if (SanOpts.has(SanitizerKind::ArrayBounds) && isa<ArraySubscriptExpr>(E))
- LV = EmitArraySubscriptExpr(cast<ArraySubscriptExpr>(E), /*Accessed*/ true);
+ LV = EmitArraySubscriptExpr(cast<ArraySubscriptExpr>(E), /*Accessed*/true);
else
LV = EmitLValue(E);
if (!isa<DeclRefExpr>(E) && !LV.isBitField() && LV.isSimple()) {
@@ -1740,8 +1747,7 @@ LValue CodeGenFunction::EmitLValueHelper(const Expr *E,
KnownNonNull_t IsKnownNonNull) {
ApplyDebugLocation DL(*this, E);
switch (E->getStmtClass()) {
- default:
- return EmitUnsupportedLValue(E, "l-value expression");
+ default: return EmitUnsupportedLValue(E, "l-value expression");
case Expr::ObjCPropertyRefExprClass:
llvm_unreachable("cannot emit a property reference directly");
@@ -1905,8 +1911,7 @@ static bool isConstantEmittableObjectType(QualType type) {
// Must be const-qualified but non-volatile.
Qualifiers qs = type.getLocalQualifiers();
- if (!qs.hasConst() || qs.hasVolatile())
- return false;
+ if (!qs.hasConst() || qs.hasVolatile()) return false;
// Otherwise, all object types satisfy this except C++ classes with
// mutable subobjects or non-trivial copy/destroy behavior.
@@ -1966,8 +1971,7 @@ CodeGenFunction::tryEmitAsConstant(const DeclRefExpr *RefExpr) {
} else {
CEK = CEK_None;
}
- if (CEK == CEK_None)
- return ConstantEmission();
+ if (CEK == CEK_None) return ConstantEmission();
Expr::EvalResult result;
bool resultIsReference;
@@ -1979,13 +1983,13 @@ CodeGenFunction::tryEmitAsConstant(const DeclRefExpr *RefExpr) {
resultIsReference = false;
resultType = RefExpr->getType().getUnqualifiedType();
- // Otherwise, try to evaluate as an l-value.
+ // Otherwise, try to evaluate as an l-value.
} else if (CEK != CEK_AsValueOnly &&
RefExpr->EvaluateAsLValue(result, getContext())) {
resultIsReference = true;
resultType = Value->getType();
- // Failure.
+ // Failure.
} else {
return ConstantEmission();
}
@@ -2145,7 +2149,8 @@ bool CodeGenFunction::EmitScalarRangeCheck(llvm::Value *Value, QualType Ty,
// Single-bit booleans don't need to be checked. Special-case this to avoid
// a bit width mismatch when handling bitfield values. This is handled by
// EmitFromMemory for the non-bitfield case.
- if (IsBool && cast<llvm::IntegerType>(Value->getType())->getBitWidth() == 1)
+ if (IsBool &&
+ cast<llvm::IntegerType>(Value->getType())->getBitWidth() == 1)
return false;
if (NeedsEnumCheck &&
@@ -2181,7 +2186,8 @@ bool CodeGenFunction::EmitScalarRangeCheck(llvm::Value *Value, QualType Ty,
}
llvm::Value *CodeGenFunction::EmitLoadOfScalar(Address Addr, bool Volatile,
- QualType Ty, SourceLocation Loc,
+ QualType Ty,
+ SourceLocation Loc,
LValueBaseInfo BaseInfo,
TBAAAccessInfo TBAAInfo,
bool isNontemporal) {
@@ -2428,8 +2434,8 @@ static void EmitStoreOfMatrixScalar(llvm::Value *value, LValue lvalue,
void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, Address Addr,
bool Volatile, QualType Ty,
LValueBaseInfo BaseInfo,
- TBAAAccessInfo TBAAInfo, bool isInit,
- bool isNontemporal) {
+ TBAAAccessInfo TBAAInfo,
+ bool isInit, bool isNontemporal) {
if (auto *GV = dyn_cast<llvm::GlobalValue>(Addr.getBasePointer()))
if (GV->isThreadLocal())
Addr = Addr.withPointer(Builder.CreateThreadLocalAddress(GV),
@@ -2542,8 +2548,8 @@ RValue CodeGenFunction::EmitLoadOfLValue(LValue LV, SourceLocation Loc) {
if (LV.isObjCWeak()) {
// load of a __weak object.
Address AddrWeakObj = LV.getAddress();
- return RValue::get(
- CGM.getObjCRuntime().EmitObjCWeakRead(*this, AddrWeakObj));
+ return RValue::get(CGM.getObjCRuntime().EmitObjCWeakRead(*this,
+ AddrWeakObj));
}
if (LV.getQuals().getObjCLifetime() == Qualifiers::OCL_Weak) {
// In MRC mode, we do a load+autorelease.
@@ -2568,8 +2574,8 @@ RValue CodeGenFunction::EmitLoadOfLValue(LValue LV, SourceLocation Loc) {
}
if (LV.isVectorElt()) {
- llvm::LoadInst *Load =
- Builder.CreateLoad(LV.getVectorAddress(), LV.isVolatileQualified());
+ llvm::LoadInst *Load = Builder.CreateLoad(LV.getVectorAddress(),
+ LV.isVolatileQualified());
llvm::Value *Elt =
Builder.CreateExtractElement(Load, LV.getVectorIdx(), "vecext");
return RValue::get(EmitFromMemory(Elt, LV.getType()));
@@ -2682,8 +2688,8 @@ RValue CodeGenFunction::EmitLoadOfBitfieldLValue(LValue LV,
// If this is a reference to a subset of the elements of a vector, create an
// appropriate shufflevector.
RValue CodeGenFunction::EmitLoadOfExtVectorElementLValue(LValue LV) {
- llvm::Value *Vec =
- Builder.CreateLoad(LV.getExtVectorAddress(), LV.isVolatileQualified());
+ llvm::Value *Vec = Builder.CreateLoad(LV.getExtVectorAddress(),
+ LV.isVolatileQualified());
// HLSL allows treating scalars as one-element vectors. Converting the scalar
// IR value to a vector here allows the rest of codegen to behave as normal.
@@ -2750,7 +2756,8 @@ Address CodeGenFunction::EmitExtVectorElementLValue(LValue LV) {
unsigned ix = getAccessedFieldNo(0, Elts);
Address VectorBasePtrPlusIx =
- Builder.CreateConstInBoundsGEP(CastToPointerElement, ix, "vector.elt");
+ Builder.CreateConstInBoundsGEP(CastToPointerElement, ix,
+ "vector.elt");
return VectorBasePtrPlusIx;
}
@@ -2767,7 +2774,7 @@ RValue CodeGenFunction::EmitLoadOfGlobalRegLValue(LValue LV) {
llvm::Type *Ty = OrigTy;
if (OrigTy->isPointerTy())
Ty = CGM.getTypes().getDataLayout().getIntPtrType(OrigTy);
- llvm::Type *Types[] = {Ty};
+ llvm::Type *Types[] = { Ty };
llvm::Function *F = CGM.getIntrinsic(llvm::Intrinsic::read_register, Types);
llvm::Value *Call = Builder.CreateCall(
@@ -2811,8 +2818,8 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst,
}
// Read/modify/write the vector, inserting the new element.
- llvm::Value *Vec =
- Builder.CreateLoad(Dst.getVectorAddress(), Dst.isVolatileQualified());
+ llvm::Value *Vec = Builder.CreateLoad(Dst.getVectorAddress(),
+ Dst.isVolatileQualified());
llvm::Type *VecTy = Vec->getType();
llvm::Value *SrcVal = Src.getScalarVal();
@@ -2999,8 +3006,8 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst,
return;
case Qualifiers::OCL_Autoreleasing:
- Src = RValue::get(
- EmitObjCExtendObjectLifetime(Dst.getType(), Src.getScalarVal()));
+ Src = RValue::get(EmitObjCExtendObjectLifetime(Dst.getType(),
+ Src.getScalarVal()));
// fall into the normal path
break;
}
@@ -3010,7 +3017,7 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst,
// load of a __weak object.
Address LvalueDst = Dst.getAddress();
llvm::Value *src = Src.getScalarVal();
- CGM.getObjCRuntime().EmitObjCWeakAssign(*this, src, LvalueDst);
+ CGM.getObjCRuntime().EmitObjCWeakAssign(*this, src, LvalueDst);
return;
}
@@ -3031,7 +3038,8 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst,
} else if (Dst.isGlobalObjCRef()) {
CGM.getObjCRuntime().EmitObjCGlobalAssign(*this, src, LvalueDst,
Dst.isThreadLocalRef());
- } else
+ }
+ else
CGM.getObjCRuntime().EmitObjCStrongCastAssign(*this, src, LvalueDst);
return;
}
@@ -3241,7 +3249,7 @@ void CodeGenFunction::EmitStoreThroughGlobalRegLValue(RValue Src, LValue Dst) {
llvm::Type *Ty = OrigTy;
if (OrigTy->isPointerTy())
Ty = CGM.getTypes().getDataLayout().getIntPtrType(OrigTy);
- llvm::Type *Types[] = {Ty};
+ llvm::Type *Types[] = { Ty };
llvm::Function *F = CGM.getIntrinsic(llvm::Intrinsic::write_register, Types);
llvm::Value *Value = Src.getScalarVal();
@@ -3255,7 +3263,8 @@ void CodeGenFunction::EmitStoreThroughGlobalRegLValue(RValue Src, LValue Dst) {
// generating write-barries API. It is currently a global, ivar,
// or neither.
static void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E,
- LValue &LV, bool IsMemberAccess = false) {
+ LValue &LV,
+ bool IsMemberAccess=false) {
if (Ctx.getLangOpts().getGC() == LangOptions::NonGC)
return;
@@ -3350,11 +3359,9 @@ static void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E,
}
}
-static LValue EmitThreadPrivateVarDeclLValue(CodeGenFunction &CGF,
- const VarDecl *VD, QualType T,
- Address Addr,
- llvm::Type *RealVarTy,
- SourceLocation Loc) {
+static LValue EmitThreadPrivateVarDeclLValue(
+ CodeGenFunction &CGF, const VarDecl *VD, QualType T, Address Addr,
+ llvm::Type *RealVarTy, SourceLocation Loc) {
if (CGF.CGM.getLangOpts().OpenMPIRBuilder)
Addr = CodeGenFunction::OMPBuilderCBHelpers::getAddrOfThreadPrivate(
CGF, VD, Addr, Loc);
@@ -3389,9 +3396,10 @@ static Address emitDeclTargetVarDeclLValue(CodeGenFunction &CGF,
return CGF.EmitLoadOfPointer(Addr, PtrTy->castAs<PointerType>());
}
-Address CodeGenFunction::EmitLoadOfReference(LValue RefLVal,
- LValueBaseInfo *PointeeBaseInfo,
- TBAAAccessInfo *PointeeTBAAInfo) {
+Address
+CodeGenFunction::EmitLoadOfReference(LValue RefLVal,
+ LValueBaseInfo *PointeeBaseInfo,
+ TBAAAccessInfo *PointeeTBAAInfo) {
llvm::LoadInst *Load =
Builder.CreateLoad(RefLVal.getAddress(), RefLVal.isVolatile());
CGM.DecorateInstructionWithTBAA(Load, RefLVal.getTBAAInfo());
@@ -3425,8 +3433,8 @@ Address CodeGenFunction::EmitLoadOfReference(LValue RefLVal,
LValue CodeGenFunction::EmitLoadOfReferenceLValue(LValue RefLVal) {
LValueBaseInfo PointeeBaseInfo;
TBAAAccessInfo PointeeTBAAInfo;
- Address PointeeAddr =
- EmitLoadOfReference(RefLVal, &PointeeBaseInfo, &PointeeTBAAInfo);
+ Address PointeeAddr = EmitLoadOfReference(RefLVal, &PointeeBaseInfo,
+ &PointeeTBAAInfo);
return MakeAddrLValue(PointeeAddr, RefLVal.getType()->getPointeeType(),
PointeeBaseInfo, PointeeTBAAInfo);
}
@@ -3449,8 +3457,8 @@ LValue CodeGenFunction::EmitLoadOfPointerLValue(Address PtrAddr,
return MakeAddrLValue(Addr, PtrTy->getPointeeType(), BaseInfo, TBAAInfo);
}
-static LValue EmitGlobalVarDeclLValue(CodeGenFunction &CGF, const Expr *E,
- const VarDecl *VD) {
+static LValue EmitGlobalVarDeclLValue(CodeGenFunction &CGF,
+ const Expr *E, const VarDecl *VD) {
QualType T = E->getType();
// If it's thread_local, emit a call to its wrapper function instead.
@@ -3489,10 +3497,10 @@ static LValue EmitGlobalVarDeclLValue(CodeGenFunction &CGF, const Expr *E,
return EmitThreadPrivateVarDeclLValue(CGF, VD, T, Addr, RealVarTy,
E->getExprLoc());
}
- LValue LV = VD->getType()->isReferenceType()
- ? CGF.EmitLoadOfReferenceLValue(Addr, VD->getType(),
- AlignmentSource::Decl)
- : CGF.MakeAddrLValue(Addr, T, AlignmentSource::Decl);
+ LValue LV = VD->getType()->isReferenceType() ?
+ CGF.EmitLoadOfReferenceLValue(Addr, VD->getType(),
+ AlignmentSource::Decl) :
+ CGF.MakeAddrLValue(Addr, T, AlignmentSource::Decl);
setObjCGCLValueClass(CGF.getContext(), E, LV);
return LV;
}
@@ -3537,12 +3545,14 @@ static LValue EmitCapturedFieldLValue(CodeGenFunction &CGF, const FieldDecl *FD,
static LValue EmitGlobalNamedRegister(const VarDecl *VD, CodeGenModule &CGM) {
SmallString<64> Name("llvm.named.register.");
AsmLabelAttr *Asm = VD->getAttr<AsmLabelAttr>();
- assert(Asm->getLabel().size() < 64 - Name.size() && "Register name too big");
+ assert(Asm->getLabel().size() < 64-Name.size() &&
+ "Register name too big");
Name.append(Asm->getLabel());
- llvm::NamedMDNode *M = CGM.getModule().getOrInsertNamedMetadata(Name);
+ llvm::NamedMDNode *M =
+ CGM.getModule().getOrInsertNamedMetadata(Name);
if (M->getNumOperands() == 0) {
- llvm::MDString *Str =
- llvm::MDString::get(CGM.getLLVMContext(), Asm->getLabel());
+ llvm::MDString *Str = llvm::MDString::get(CGM.getLLVMContext(),
+ Asm->getLabel());
llvm::Metadata *Ops[] = {Str};
M->addOperand(llvm::MDNode::get(CGM.getLLVMContext(), Ops));
}
@@ -3550,7 +3560,7 @@ static LValue EmitGlobalNamedRegister(const VarDecl *VD, CodeGenModule &CGM) {
CharUnits Alignment = CGM.getContext().getDeclAlign(VD);
llvm::Value *Ptr =
- llvm::MetadataAsValue::get(CGM.getLLVMContext(), M->getOperand(0));
+ llvm::MetadataAsValue::get(CGM.getLLVMContext(), M->getOperand(0));
return LValue::MakeGlobalReg(Ptr, Alignment, VD->getType());
}
@@ -3613,8 +3623,8 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
if (const auto *VD = dyn_cast<VarDecl>(ND)) {
// Global Named registers access via intrinsics only
- if (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
- !VD->isLocalVarDecl())
+ if (VD->getStorageClass() == SC_Register &&
+ VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())
return EmitGlobalNamedRegister(VD, CGM);
// If this DeclRefExpr does not constitute an odr-use of the variable,
@@ -3722,15 +3732,15 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
if (iter != LocalDeclMap.end()) {
addr = iter->second;
- // Otherwise, it might be static local we haven't emitted yet for
- // some reason; most likely, because it's in an outer function.
+ // Otherwise, it might be static local we haven't emitted yet for
+ // some reason; most likely, because it's in an outer function.
} else if (VD->isStaticLocal()) {
llvm::Constant *var = CGM.getOrCreateStaticVarDecl(
*VD, CGM.getLLVMLinkageVarDefinition(VD));
- addr = Address(var, ConvertTypeForMem(VD->getType()),
- getContext().getDeclAlign(VD));
+ addr = Address(
+ var, ConvertTypeForMem(VD->getType()), getContext().getDeclAlign(VD));
- // No other cases for now.
+ // No other cases for now.
} else {
llvm_unreachable("DeclRefExpr for Decl not entered in LocalDeclMap?");
}
@@ -3756,22 +3766,22 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
}
// Drill into reference types.
- LValue LV = VD->getType()->isReferenceType()
- ? EmitLoadOfReferenceLValue(addr, VD->getType(),
- AlignmentSource::Decl)
- : MakeAddrLValue(addr, T, AlignmentSource::Decl);
+ LValue LV = VD->getType()->isReferenceType() ?
+ EmitLoadOfReferenceLValue(addr, VD->getType(), AlignmentSource::Decl) :
+ MakeAddrLValue(addr, T, AlignmentSource::Decl);
bool isLocalStorage = VD->hasLocalStorage();
- bool NonGCable =
- isLocalStorage && !VD->getType()->isReferenceType() && !isBlockByref;
+ bool NonGCable = isLocalStorage &&
+ !VD->getType()->isReferenceType() &&
+ !isBlockByref;
if (NonGCable) {
LV.getQuals().removeObjCGCAttr();
LV.setNonGC(true);
}
bool isImpreciseLifetime =
- (isLocalStorage && !VD->hasAttr<ObjCPreciseLifetimeAttr>());
+ (isLocalStorage && !VD->hasAttr<ObjCPreciseLifetimeAttr>());
if (isImpreciseLifetime)
LV.setARCPreciseLifetime(ARCImpreciseLifetime);
setObjCGCLValueClass(getContext(), E, LV);
@@ -3830,16 +3840,15 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) {
QualType ExprTy = getContext().getCanonicalType(E->getSubExpr()->getType());
switch (E->getOpcode()) {
- default:
- llvm_unreachable("Unknown unary operator lvalue!");
+ default: llvm_unreachable("Unknown unary operator lvalue!");
case UO_Deref: {
QualType T = E->getSubExpr()->getType()->getPointeeType();
assert(!T.isNull() && "CodeGenFunction::EmitUnaryOpLValue: Illegal type");
LValueBaseInfo BaseInfo;
TBAAAccessInfo TBAAInfo;
- Address Addr =
- EmitPointerWithAlignment(E->getSubExpr(), &BaseInfo, &TBAAInfo);
+ Address Addr = EmitPointerWithAlignment(E->getSubExpr(), &BaseInfo,
+ &TBAAInfo);
LValue LV = MakeAddrLValue(Addr, T, BaseInfo, TBAAInfo);
LV.getQuals().setAddressSpace(ExprTy.getAddressSpace());
@@ -3847,7 +3856,8 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) {
// of a pointer to object; as in void foo (__weak id *param); *param = 0;
// But, we continue to generate __strong write barrier on indirect write
// into a pointer to object.
- if (getLangOpts().ObjC && getLangOpts().getGC() != LangOptions::NonGC &&
+ if (getLangOpts().ObjC &&
+ getLangOpts().getGC() != LangOptions::NonGC &&
LV.isObjCWeak())
LV.setNonGC(!E->isOBJCGCCandidate(getContext()));
return LV;
@@ -3882,17 +3892,17 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) {
bool isInc = E->getOpcode() == UO_PreInc;
if (E->getType()->isAnyComplexType())
- EmitComplexPrePostIncDec(E, LV, isInc, true /*isPre*/);
+ EmitComplexPrePostIncDec(E, LV, isInc, true/*isPre*/);
else
- EmitScalarPrePostIncDec(E, LV, isInc, true /*isPre*/);
+ EmitScalarPrePostIncDec(E, LV, isInc, true/*isPre*/);
return LV;
}
}
}
LValue CodeGenFunction::EmitStringLiteralLValue(const StringLiteral *E) {
- return MakeAddrLValue(CGM.GetAddrOfConstantStringFromLiteral(E), E->getType(),
- AlignmentSource::Decl);
+ return MakeAddrLValue(CGM.GetAddrOfConstantStringFromLiteral(E),
+ E->getType(), AlignmentSource::Decl);
}
LValue CodeGenFunction::EmitObjCEncodeExprLValue(const ObjCEncodeExpr *E) {
@@ -3905,8 +3915,8 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) {
assert(SL != nullptr && "No StringLiteral name in PredefinedExpr");
StringRef FnName = CurFn->getName();
FnName.consume_front("\01");
- StringRef NameItems[] = {PredefinedExpr::getIdentKindName(E->getIdentKind()),
- FnName};
+ StringRef NameItems[] = {
+ PredefinedExpr::getIdentKindName(E->getIdentKind()), FnName};
std::string GVName = llvm::join(NameItems, NameItems + 2, ".");
if (auto *BD = dyn_cast_or_null<BlockDecl>(CurCodeDecl)) {
std::string Name = std::string(SL->getString());
@@ -3992,8 +4002,9 @@ llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) {
}
llvm::Constant *Components[] = {
- Builder.getInt16(TypeKind), Builder.getInt16(TypeInfo),
- llvm::ConstantDataArray::getString(getLLVMContext(), Buffer)};
+ Builder.getInt16(TypeKind), Builder.getInt16(TypeInfo),
+ llvm::ConstantDataArray::getString(getLLVMContext(), Buffer)
+ };
llvm::Constant *Descriptor = llvm::ConstantStruct::getAnon(Components);
auto *GV = new llvm::GlobalVariable(
@@ -4019,8 +4030,8 @@ llvm::Value *CodeGenFunction::EmitCheckValue(llvm::Value *V) {
if (V->getType()->isFloatingPointTy()) {
unsigned Bits = V->getType()->getPrimitiveSizeInBits().getFixedValue();
if (Bits <= TargetTy->getIntegerBitWidth())
- V = Builder.CreateBitCast(V,
- llvm::Type::getIntNTy(getLLVMContext(), Bits));
+ V = Builder.CreateBitCast(V, llvm::Type::getIntNTy(getLLVMContext(),
+ Bits));
}
// Integers which fit in intptr_t are zero-extended and passed directly.
@@ -4108,7 +4119,7 @@ enum class CheckRecoverableKind {
/// Runtime conditionally aborts, always need to support recovery.
AlwaysRecoverable
};
-} // namespace
+}
static CheckRecoverableKind
getRecoverableKind(SanitizerKind::SanitizerOrdinal Ordinal) {
@@ -4126,7 +4137,7 @@ struct SanitizerHandlerInfo {
char const *const Name;
unsigned Version;
};
-} // namespace
+}
const SanitizerHandlerInfo SanitizerHandlers[] = {
#define SANITIZER_CHECK(Enum, Name, Version, Msg) {#Name, Version},
@@ -4303,7 +4314,7 @@ void CodeGenFunction::EmitCheck(
}
llvm::FunctionType *FnType =
- llvm::FunctionType::get(CGM.VoidTy, ArgTypes, false);
+ llvm::FunctionType::get(CGM.VoidTy, ArgTypes, false);
if (!FatalCond || !RecoverableCond) {
// Simple case: we need to generate a single handler call, either
@@ -4402,7 +4413,7 @@ void CodeGenFunction::EmitCfiCheckStub() {
llvm::LLVMContext &Ctx = M->getContext();
llvm::BasicBlock *BB = llvm::BasicBlock::Create(Ctx, "entry", F);
// CrossDSOCFI pass is not executed if there is no executable code.
- SmallVector<llvm::Value *> Args{F->getArg(2), F->getArg(1)};
+ SmallVector<llvm::Value*> Args{F->getArg(2), F->getArg(1)};
llvm::CallInst::Create(M->getFunction("__cfi_check_fail"), Args, "", BB);
llvm::ReturnInst::Create(Ctx, nullptr, BB);
}
@@ -4432,8 +4443,8 @@ void CodeGenFunction::EmitCfiCheckFail() {
getContext(), getContext().VoidPtrTy, ImplicitParamKind::Other);
FunctionArgList Args{ArgData, ArgAddr};
- const CGFunctionInfo &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
- getContext().VoidTy, Args);
+ const CGFunctionInfo &FI =
+ CGM.getTypes().arrangeBuiltinFunctionDeclaration(getContext().VoidTy, Args);
llvm::Function *F = llvm::Function::Create(
llvm::FunctionType::get(VoidTy, {VoidPtrTy, VoidPtrTy}, false),
@@ -4686,10 +4697,8 @@ Address CodeGenFunction::EmitArrayToPointerDecay(const Expr *E,
// to the pointee object as if it had no any base lvalue specified.
// TODO: Support TBAA for member arrays.
QualType EltType = E->getType()->castAsArrayTypeUnsafe()->getElementType();
- if (BaseInfo)
- *BaseInfo = LV.getBaseInfo();
- if (TBAAInfo)
- *TBAAInfo = CGM.getTBAAAccessInfo(EltType);
+ if (BaseInfo) *BaseInfo = LV.getBaseInfo();
+ if (TBAAInfo) *TBAAInfo = CGM.getTBAAAccessInfo(EltType);
return Addr.withElementType(ConvertTypeForMem(EltType));
}
@@ -4710,11 +4719,14 @@ static const Expr *isSimpleArrayDecayOperand(const Expr *E) {
return SubExpr;
}
-static llvm::Value *
-emitArraySubscriptGEP(CodeGenFunction &CGF, llvm::Type *elemType,
- llvm::Value *ptr, ArrayRef<llvm::Value *> indices,
- bool inbounds, bool signedIndices, SourceLocation loc,
- const llvm::Twine &name = "arrayidx") {
+static llvm::Value *emitArraySubscriptGEP(CodeGenFunction &CGF,
+ llvm::Type *elemType,
+ llvm::Value *ptr,
+ ArrayRef<llvm::Value*> indices,
+ bool inbounds,
+ bool signedIndices,
+ SourceLocation loc,
+ const llvm::Twine &name = "arrayidx") {
if (inbounds && CGF.getLangOpts().EmitLogicalPointer)
return CGF.Builder.CreateStructuredGEP(elemType, ptr, indices);
@@ -4811,8 +4823,8 @@ static bool IsPreserveAIArrayBase(CodeGenFunction &CGF, const Expr *ArrayBase) {
if (!PtrT)
return false;
- const auto *PointeeT =
- PtrT->getPointeeType()->getUnqualifiedDesugaredType();
+ const auto *PointeeT = PtrT->getPointeeType()
+ ->getUnqualifiedDesugaredType();
if (const auto *RecT = dyn_cast<RecordType>(PointeeT))
return RecT->getDecl()
->getMostRecentDecl()
@@ -5040,7 +5052,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
!isa<ExtVectorElementExpr>(E->getBase())) {
// Emit the vector as an lvalue to get its address.
LValue LHS = EmitLValue(E->getBase());
- auto *Idx = EmitIdxAfterBase(/*Promote*/ false);
+ auto *Idx = EmitIdxAfterBase(/*Promote*/false);
assert(LHS.isSimple() && "Can only subscript lvalue vectors here!");
return LValue::MakeVectorElt(LHS.getAddress(), Idx, E->getBase()->getType(),
LHS.getBaseInfo(), TBAAAccessInfo());
@@ -5066,7 +5078,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
// Handle the extvector case we ignored above.
if (isa<ExtVectorElementExpr>(E->getBase())) {
LValue LV = EmitLValue(E->getBase());
- auto *Idx = EmitIdxAfterBase(/*Promote*/ true);
+ auto *Idx = EmitIdxAfterBase(/*Promote*/true);
Address Addr = EmitExtVectorElementLValue(LV);
QualType EltType = LV.getType()->castAs<VectorType>()->getElementType();
@@ -5080,12 +5092,12 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
TBAAAccessInfo EltTBAAInfo;
Address Addr = Address::invalid();
if (const VariableArrayType *vla =
- getContext().getAsVariableArrayType(E->getType())) {
+ getContext().getAsVariableArrayType(E->getType())) {
// The base must be a pointer, which is not an aggregate. Emit
// it. It needs to be emitted first in case it's what captures
// the VLA bounds.
Addr = EmitPointerWithAlignment(E->getBase(), &EltBaseInfo, &EltTBAAInfo);
- auto *Idx = EmitIdxAfterBase(/*Promote*/ true);
+ auto *Idx = EmitIdxAfterBase(/*Promote*/true);
// The element count here is the total number of non-VLA elements.
llvm::Value *numElements = getVLASize(vla).NumElts;
@@ -5104,13 +5116,12 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
!getLangOpts().PointerOverflowDefined,
SignedIndices, E->getExprLoc());
- } else if (const ObjCObjectType *OIT =
- E->getType()->getAs<ObjCObjectType>()) {
+ } else if (const ObjCObjectType *OIT = E->getType()->getAs<ObjCObjectType>()){
// Indexing over an interface, as in "NSString *P; P[4];"
// Emit the base pointer.
Addr = EmitPointerWithAlignment(E->getBase(), &EltBaseInfo, &EltTBAAInfo);
- auto *Idx = EmitIdxAfterBase(/*Promote*/ true);
+ auto *Idx = EmitIdxAfterBase(/*Promote*/true);
CharUnits InterfaceSize = getContext().getTypeSizeInChars(OIT);
llvm::Value *InterfaceSizeVal =
@@ -5126,7 +5137,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
// Do the GEP.
CharUnits EltAlign =
- getArrayElementAlign(Addr.getAlignment(), Idx, InterfaceSize);
+ getArrayElementAlign(Addr.getAlignment(), Idx, InterfaceSize);
llvm::Value *EltPtr =
emitArraySubscriptGEP(*this, Int8Ty, Addr.emitRawPointer(*this),
ScaledIdx, false, SignedIndices, E->getExprLoc());
@@ -5145,7 +5156,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
ArrayLV = EmitArraySubscriptExpr(ASE, /*Accessed*/ true);
else
ArrayLV = EmitLValue(Array);
- auto *Idx = EmitIdxAfterBase(/*Promote*/ true);
+ auto *Idx = EmitIdxAfterBase(/*Promote*/true);
if (SanOpts.has(SanitizerKind::ArrayBounds))
EmitCountedByBoundsChecking(Array, Array->getType(), ArrayLV.getAddress(),
@@ -5189,7 +5200,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
// The base must be a pointer; emit it with an estimate of its alignment.
Address BaseAddr =
EmitPointerWithAlignment(E->getBase(), &EltBaseInfo, &EltTBAAInfo);
- auto *Idx = EmitIdxAfterBase(/*Promote*/ true);
+ auto *Idx = EmitIdxAfterBase(/*Promote*/true);
QualType ptrType = E->getBase()->getType();
Addr = emitArraySubscriptGEP(*this, BaseAddr, Idx, E->getType(),
!getLangOpts().PointerOverflowDefined,
@@ -5210,7 +5221,8 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
LValue LV = MakeAddrLValue(Addr, E->getType(), EltBaseInfo, EltTBAAInfo);
- if (getLangOpts().ObjC && getLangOpts().getGC() != LangOptions::NonGC) {
+ if (getLangOpts().ObjC &&
+ getLangOpts().getGC() != LangOptions::NonGC) {
LV.setNonGC(!E->isOBJCGCCandidate(getContext()));
setObjCGCLValueClass(getContext(), E, LV);
}
@@ -5360,10 +5372,11 @@ LValue CodeGenFunction::EmitArraySectionExpr(const ArraySectionExpr *E,
LowerBound->getType()->hasSignedIntegerRepresentation())
: llvm::ConstantInt::get(IntPtrTy, ConstLowerBound);
auto *LengthVal =
- Length ? Builder.CreateIntCast(
- EmitScalarExpr(Length), IntPtrTy,
- Length->getType()->hasSignedIntegerRepresentation())
- : llvm::ConstantInt::get(IntPtrTy, ConstLength);
+ Length
+ ? Builder.CreateIntCast(
+ EmitScalarExpr(Length), IntPtrTy,
+ Length->getType()->hasSignedIntegerRepresentation())
+ : llvm::ConstantInt::get(IntPtrTy, ConstLength);
Idx = Builder.CreateAdd(LowerBoundVal, LengthVal, "lb_add_len",
/*HasNUW=*/false,
!getLangOpts().PointerOverflowDefined);
@@ -5414,8 +5427,8 @@ LValue CodeGenFunction::EmitArraySectionExpr(const ArraySectionExpr *E,
// it. It needs to be emitted first in case it's what captures
// the VLA bounds.
Address Base =
- emitOMPArraySectionBase(*this, E->getBase(), BaseInfo, TBAAInfo, BaseTy,
- VLA->getElementType(), IsLowerBound);
+ emitOMPArraySectionBase(*this, E->getBase(), BaseInfo, TBAAInfo,
+ BaseTy, VLA->getElementType(), IsLowerBound);
// The element count here is the total number of non-VLA elements.
llvm::Value *NumElements = getVLASize(VLA).NumElts;
@@ -5464,8 +5477,8 @@ LValue CodeGenFunction::EmitArraySectionExpr(const ArraySectionExpr *E,
return MakeAddrLValue(EltPtr, ResultExprTy, BaseInfo, TBAAInfo);
}
-LValue
-CodeGenFunction::EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
+LValue CodeGenFunction::
+EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
// Emit the base vector as an l-value.
LValue Base;
@@ -5502,7 +5515,7 @@ CodeGenFunction::EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
}
QualType type =
- E->getType().withCVRQualifiers(Base.getQuals().getCVRQualifiers());
+ E->getType().withCVRQualifiers(Base.getQuals().getCVRQualifiers());
// Encode the element access list into a vector of unsigned indices.
SmallVector<uint32_t, 4> Indices;
@@ -5729,7 +5742,7 @@ static Address emitRawAddrOfFieldStorage(CodeGenFunction &CGF, Address base,
const RecordDecl *rec = field->getParent();
unsigned idx =
- CGF.CGM.getTypes().getCGRecordLayout(rec).getLLVMFieldNo(field);
+ CGF.CGM.getTypes().getCGRecordLayout(rec).getLLVMFieldNo(field);
llvm::Type *StructType =
CGF.CGM.getTypes().getCGRecordLayout(rec).getLLVMType();
@@ -5856,8 +5869,8 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, const FieldDecl *field,
AlignmentSource BaseAlignSource = BaseInfo.getAlignmentSource();
LValueBaseInfo FieldBaseInfo(getFieldAlignmentSource(BaseAlignSource));
TBAAAccessInfo FieldTBAAInfo;
- if (base.getTBAAInfo().isMayAlias() || rec->hasAttr<MayAliasAttr>() ||
- FieldType->isVectorType()) {
+ if (base.getTBAAInfo().isMayAlias() ||
+ rec->hasAttr<MayAliasAttr>() || FieldType->isVectorType()) {
FieldTBAAInfo = TBAAAccessInfo::getMayAliasInfo();
} else if (rec->isUnion()) {
// TODO: Support TBAA for unions.
@@ -5867,9 +5880,9 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, const FieldDecl *field,
// one for this base lvalue.
FieldTBAAInfo = base.getTBAAInfo();
if (!FieldTBAAInfo.BaseType) {
- FieldTBAAInfo.BaseType = CGM.getTBAABaseTypeInfo(base.getType());
- assert(!FieldTBAAInfo.Offset &&
- "Nonzero offset for an access with no base type!");
+ FieldTBAAInfo.BaseType = CGM.getTBAABaseTypeInfo(base.getType());
+ assert(!FieldTBAAInfo.Offset &&
+ "Nonzero offset for an access with no base type!");
}
// Adjust offset to be relative to the base type.
@@ -5914,8 +5927,8 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, const FieldDecl *field,
if (IsInPreservedAIRegion ||
(getDebugInfo() && rec->hasAttr<BPFPreserveAccessIndexAttr>())) {
// Remember the original union field index
- llvm::DIType *DbgInfo = getDebugInfo()->getOrCreateStandaloneType(
- base.getType(), rec->getLocation());
+ llvm::DIType *DbgInfo = getDebugInfo()->getOrCreateStandaloneType(base.getType(),
+ rec->getLocation());
addr =
Address(Builder.CreatePreserveUnionAccessIndex(
addr.emitRawPointer(*this),
@@ -6054,7 +6067,7 @@ LValue CodeGenFunction::EmitInitListLValue(const InitListExpr *E) {
static std::optional<LValue> EmitLValueOrThrowExpression(CodeGenFunction &CGF,
const Expr *Operand) {
if (auto *ThrowExpr = dyn_cast<CXXThrowExpr>(Operand->IgnoreParens())) {
- CGF.EmitCXXThrowExpr(ThrowExpr, /*KeepInsertionPoint*/ false);
+ CGF.EmitCXXThrowExpr(ThrowExpr, /*KeepInsertionPoint*/false);
return std::nullopt;
}
@@ -6101,7 +6114,7 @@ struct ConditionalInfo {
// Create and generate the 3 blocks for a conditional operator.
// Leaves the 'current block' in the continuation basic block.
-template <typename FuncTy>
+template<typename FuncTy>
ConditionalInfo EmitConditionalBlocks(CodeGenFunction &CGF,
const AbstractConditionalOperator *E,
const FuncTy &BranchGenFunc) {
@@ -6440,8 +6453,8 @@ LValue
CodeGenFunction::getOrCreateOpaqueLValueMapping(const OpaqueValueExpr *e) {
assert(OpaqueValueMapping::shouldBindAsLValue(e));
- llvm::DenseMap<const OpaqueValueExpr *, LValue>::iterator it =
- OpaqueLValues.find(e);
+ llvm::DenseMap<const OpaqueValueExpr*,LValue>::iterator
+ it = OpaqueLValues.find(e);
if (it != OpaqueLValues.end())
return it->second;
@@ -6454,8 +6467,8 @@ RValue
CodeGenFunction::getOrCreateOpaqueRValueMapping(const OpaqueValueExpr *e) {
assert(!OpaqueValueMapping::shouldBindAsLValue(e));
- llvm::DenseMap<const OpaqueValueExpr *, RValue>::iterator it =
- OpaqueRValues.find(e);
+ llvm::DenseMap<const OpaqueValueExpr*,RValue>::iterator
+ it = OpaqueRValues.find(e);
if (it != OpaqueRValues.end())
return it->second;
@@ -6470,7 +6483,8 @@ bool CodeGenFunction::isOpaqueValueEmitted(const OpaqueValueExpr *E) {
return OpaqueRValues.contains(E);
}
-RValue CodeGenFunction::EmitRValueForField(LValue LV, const FieldDecl *FD,
+RValue CodeGenFunction::EmitRValueForField(LValue LV,
+ const FieldDecl *FD,
SourceLocation Loc) {
QualType FT = FD->getType();
LValue FieldLV = EmitLValueForField(LV, FD);
@@ -6534,8 +6548,8 @@ RValue CodeGenFunction::EmitCallExpr(const CallExpr *E,
CGCallee callee = EmitCallee(E->getCallee());
if (callee.isBuiltin()) {
- return EmitBuiltinExpr(callee.getBuiltinDecl(), callee.getBuiltinID(), E,
- ReturnValue);
+ return EmitBuiltinExpr(callee.getBuiltinDecl(), callee.getBuiltinID(),
+ E, ReturnValue);
}
if (callee.isPseudoDestructor()) {
@@ -6672,7 +6686,7 @@ CGCallee CodeGenFunction::EmitCallee(const Expr *E) {
}
}
- // Resolve direct calls.
+ // Resolve direct calls.
} else if (auto DRE = dyn_cast<DeclRefExpr>(E)) {
if (auto FD = dyn_cast<FunctionDecl>(DRE->getDecl())) {
return EmitDirectCallee(*this, getGlobalDeclForDirectCall(FD));
@@ -6683,11 +6697,11 @@ CGCallee CodeGenFunction::EmitCallee(const Expr *E) {
return EmitDirectCallee(*this, FD);
}
- // Look through template substitutions.
+ // Look through template substitutions.
} else if (auto NTTP = dyn_cast<SubstNonTypeTemplateParmExpr>(E)) {
return EmitCallee(NTTP->getReplacement());
- // Treat pseudo-destructor calls differently.
+ // Treat pseudo-destructor calls differently.
} else if (auto PDE = dyn_cast<CXXPseudoDestructorExpr>(E)) {
return CGCallee::forPseudoDestructor(PDE);
}
@@ -6723,7 +6737,8 @@ LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) {
return EmitLValue(E->getRHS());
}
- if (E->getOpcode() == BO_PtrMemD || E->getOpcode() == BO_PtrMemI)
+ if (E->getOpcode() == BO_PtrMemD ||
+ E->getOpcode() == BO_PtrMemI)
return EmitPointerToDataMemberBinaryExpr(E);
assert(E->getOpcode() == BO_Assign && "unexpected binary l-value");
@@ -6872,14 +6887,15 @@ LValue CodeGenFunction::EmitVAArgExprLValue(const VAArgExpr *E) {
}
LValue CodeGenFunction::EmitCXXConstructLValue(const CXXConstructExpr *E) {
- assert(E->getType()->getAsCXXRecordDecl()->hasTrivialDestructor() &&
- "binding l-value to type which needs a temporary");
+ assert(E->getType()->getAsCXXRecordDecl()->hasTrivialDestructor()
+ && "binding l-value to type which needs a temporary");
AggValueSlot Slot = CreateAggTemp(E->getType());
EmitCXXConstructExpr(E, Slot);
return MakeAddrLValue(Slot.getAddress(), E->getType(), AlignmentSource::Decl);
}
-LValue CodeGenFunction::EmitCXXTypeidLValue(const CXXTypeidExpr *E) {
+LValue
+CodeGenFunction::EmitCXXTypeidLValue(const CXXTypeidExpr *E) {
return MakeNaturalAlignRawAddrLValue(EmitCXXTypeidExpr(E), E->getType());
}
@@ -6917,7 +6933,8 @@ LValue CodeGenFunction::EmitObjCMessageExprLValue(const ObjCMessageExpr *E) {
}
LValue CodeGenFunction::EmitObjCSelectorLValue(const ObjCSelectorExpr *E) {
- Address V = CGM.getObjCRuntime().GetAddrOfSelector(*this, E->getSelector());
+ Address V =
+ CGM.getObjCRuntime().GetAddrOfSelector(*this, E->getSelector());
return MakeAddrLValue(V, E->getType(), AlignmentSource::Decl);
}
@@ -6960,8 +6977,9 @@ LValue CodeGenFunction::EmitObjCIvarRefLValue(const ObjCIvarRefExpr *E) {
BaseQuals = ObjectTy.getQualifiers();
}
- LValue LV = EmitLValueForIvar(ObjectTy, BaseValue, E->getDecl(),
- BaseQuals.getCVRQualifiers());
+ LValue LV =
+ EmitLValueForIvar(ObjectTy, BaseValue, E->getDecl(),
+ BaseQuals.getCVRQualifiers());
setObjCGCLValueClass(getContext(), E, LV);
return LV;
}
@@ -7230,8 +7248,8 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType,
return Call;
}
-LValue
-CodeGenFunction::EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E) {
+LValue CodeGenFunction::
+EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E) {
Address BaseAddr = Address::invalid();
if (E->getOpcode() == BO_PtrMemI) {
BaseAddr = EmitPointerWithAlignment(E->getLHS());
@@ -7254,7 +7272,8 @@ CodeGenFunction::EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E) {
/// Given the address of a temporary variable, produce an r-value of
/// its type.
-RValue CodeGenFunction::convertTempToRValue(Address addr, QualType type,
+RValue CodeGenFunction::convertTempToRValue(Address addr,
+ QualType type,
SourceLocation loc) {
LValue lvalue = MakeAddrLValue(addr, type, AlignmentSource::Decl);
switch (getEvaluationKind(type)) {
@@ -7324,24 +7343,24 @@ void CodeGenFunction::SetDivFPAccuracy(llvm::Value *Val) {
}
namespace {
-struct LValueOrRValue {
- LValue LV;
- RValue RV;
-};
-} // namespace
+ struct LValueOrRValue {
+ LValue LV;
+ RValue RV;
+ };
+}
static LValueOrRValue emitPseudoObjectExpr(CodeGenFunction &CGF,
const PseudoObjectExpr *E,
- bool forLValue, AggValueSlot slot) {
+ bool forLValue,
+ AggValueSlot slot) {
SmallVector<CodeGenFunction::OpaqueValueMappingData, 4> opaques;
// Find the result expression, if any.
const Expr *resultExpr = E->getResultExpr();
LValueOrRValue result;
- for (PseudoObjectExpr::const_semantics_iterator i = E->semantics_begin(),
- e = E->semantics_end();
- i != e; ++i) {
+ for (PseudoObjectExpr::const_semantics_iterator
+ i = E->semantics_begin(), e = E->semantics_end(); i != e; ++i) {
const Expr *semantic = *i;
// If this semantic expression is an opaque value, bind it
@@ -7366,7 +7385,7 @@ static LValueOrRValue emitPseudoObjectExpr(CodeGenFunction &CGF,
opaqueData = OVMA::bind(CGF, ov, LV);
result.RV = slot.asRValue();
- // Otherwise, emit as normal.
+ // Otherwise, emit as normal.
} else {
opaqueData = OVMA::bind(CGF, ov, ov->getSourceExpr());
@@ -7381,15 +7400,15 @@ static LValueOrRValue emitPseudoObjectExpr(CodeGenFunction &CGF,
opaques.push_back(opaqueData);
- // Otherwise, if the expression is the result, evaluate it
- // and remember the result.
+ // Otherwise, if the expression is the result, evaluate it
+ // and remember the result.
} else if (semantic == resultExpr) {
if (forLValue)
result.LV = CGF.EmitLValue(semantic);
else
result.RV = CGF.EmitAnyExpr(semantic, slot);
- // Otherwise, evaluate the expression in an ignored context.
+ // Otherwise, evaluate the expression in an ignored context.
} else {
CGF.EmitIgnoredExpr(semantic);
}
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 1a90d53a88e34..062cacc98244e 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -178,7 +178,7 @@ void Sema::NoteDeletedFunction(FunctionDecl *Decl) {
return NoteDeletedInheritingConstructor(Ctor);
Diag(Decl->getLocation(), diag::note_availability_specified_here)
- << Decl << 1;
+ << Decl << 1;
}
/// Determine whether a FunctionDecl was ever declared with an
@@ -256,7 +256,7 @@ void Sema::MaybeSuggestAddingStaticToDecl(const FunctionDecl *Cur) {
if (!hasAnyExplicitStorageClass(First)) {
SourceLocation DeclBegin = First->getSourceRange().getBegin();
Diag(DeclBegin, diag::note_convert_inline_to_static)
- << Cur << FixItHint::CreateInsertion(DeclBegin, "static ");
+ << Cur << FixItHint::CreateInsertion(DeclBegin, "static ");
}
}
@@ -295,7 +295,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
if (ParsingInitForAutoVars.count(D)) {
if (isa<BindingDecl>(D)) {
Diag(Loc, diag::err_binding_cannot_appear_in_own_initializer)
- << D->getDeclName();
+ << D->getDeclName();
} else {
Diag(Loc, diag::err_auto_variable_cannot_appear_in_own_initializer)
<< diag::ParsingInitFor::Var << D->getDeclName()
@@ -337,7 +337,8 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
// constraint expression, for example)
return true;
if (!Satisfaction.IsSatisfied) {
- Diag(Loc, diag::err_reference_to_function_with_unsatisfied_constraints)
+ Diag(Loc,
+ diag::err_reference_to_function_with_unsatisfied_constraints)
<< D;
DiagnoseUnsatisfiedConstraint(Satisfaction);
return true;
@@ -352,6 +353,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
if (getLangOpts().CUDA && !CUDA().CheckCall(Loc, FD))
return true;
+
}
if (auto *Concept = dyn_cast<ConceptDecl>(D);
@@ -365,12 +367,12 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
cast<CXXConstructorDecl>(MD)->isDefaultConstructor()) ||
MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator())) {
Diag(Loc, diag::warn_cxx17_compat_lambda_def_ctor_assign)
- << !isa<CXXConstructorDecl>(MD);
+ << !isa<CXXConstructorDecl>(MD);
}
}
- auto getReferencedObjCProp =
- [](const NamedDecl *D) -> const ObjCPropertyDecl * {
+ auto getReferencedObjCProp = [](const NamedDecl *D) ->
+ const ObjCPropertyDecl * {
if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
return MD->findPropertyDecl();
return nullptr;
@@ -379,7 +381,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
if (diagnoseArgIndependentDiagnoseIfAttrs(ObjCPDecl, Loc))
return true;
} else if (diagnoseArgIndependentDiagnoseIfAttrs(D, Loc)) {
- return true;
+ return true;
}
// [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
@@ -558,8 +560,7 @@ ExprResult Sema::DefaultFunctionArrayConversion(Expr *E, bool Diagnose) {
// Handle any placeholder expressions which made it here.
if (E->hasPlaceholderType()) {
ExprResult result = CheckPlaceholderExpr(E);
- if (result.isInvalid())
- return ExprError();
+ if (result.isInvalid()) return ExprError();
E = result.get();
}
@@ -573,8 +574,7 @@ ExprResult Sema::DefaultFunctionArrayConversion(Expr *E, bool Diagnose) {
return ExprError();
E = ImpCastExprToType(E, Context.getPointerType(Ty),
- CK_FunctionToPointerDecay)
- .get();
+ CK_FunctionToPointerDecay).get();
} else if (Ty->isArrayType()) {
// In C90 mode, arrays only promote to pointers if the array expression is
// an lvalue. The relevant legalese is C90 6.2.2.1p3: "an lvalue that has
@@ -624,7 +624,8 @@ static void CheckForNullPointerDereference(Sema &S, Expr *E) {
}
static void DiagnoseDirectIsaAccess(Sema &S, const ObjCIvarRefExpr *OIRE,
- SourceLocation AssignLoc, const Expr *RHS) {
+ SourceLocation AssignLoc,
+ const Expr* RHS) {
const ObjCIvarDecl *IV = OIRE->getDecl();
if (!IV)
return;
@@ -642,12 +643,13 @@ static void DiagnoseDirectIsaAccess(Sema &S, const ObjCIvarRefExpr *OIRE,
if (ObjCInterfaceDecl *IDecl = OTy->getInterface()) {
ObjCInterfaceDecl *ClassDeclared = nullptr;
ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(Member, ClassDeclared);
- if (!ClassDeclared->getSuperClass() &&
- (*ClassDeclared->ivar_begin()) == IV) {
+ if (!ClassDeclared->getSuperClass()
+ && (*ClassDeclared->ivar_begin()) == IV) {
if (RHS) {
- NamedDecl *ObjectSetClass = S.LookupSingleName(
- S.TUScope, &S.Context.Idents.get("object_setClass"),
- SourceLocation(), S.LookupOrdinaryName);
+ NamedDecl *ObjectSetClass =
+ S.LookupSingleName(S.TUScope,
+ &S.Context.Idents.get("object_setClass"),
+ SourceLocation(), S.LookupOrdinaryName);
if (ObjectSetClass) {
SourceLocation RHSLocEnd = S.getLocForEndOfToken(RHS->getEndLoc());
S.Diag(OIRE->getExprLoc(), diag::warn_objc_isa_assign)
@@ -656,12 +658,14 @@ static void DiagnoseDirectIsaAccess(Sema &S, const ObjCIvarRefExpr *OIRE,
<< FixItHint::CreateReplacement(
SourceRange(OIRE->getOpLoc(), AssignLoc), ",")
<< FixItHint::CreateInsertion(RHSLocEnd, ")");
- } else
+ }
+ else
S.Diag(OIRE->getLocation(), diag::warn_objc_isa_assign);
} else {
- NamedDecl *ObjectGetClass = S.LookupSingleName(
- S.TUScope, &S.Context.Idents.get("object_getClass"),
- SourceLocation(), S.LookupOrdinaryName);
+ NamedDecl *ObjectGetClass =
+ S.LookupSingleName(S.TUScope,
+ &S.Context.Idents.get("object_getClass"),
+ SourceLocation(), S.LookupOrdinaryName);
if (ObjectGetClass)
S.Diag(OIRE->getExprLoc(), diag::warn_objc_isa_use)
<< FixItHint::CreateInsertion(OIRE->getBeginLoc(),
@@ -680,16 +684,14 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) {
// Handle any placeholder expressions which made it here.
if (E->hasPlaceholderType()) {
ExprResult result = CheckPlaceholderExpr(E);
- if (result.isInvalid())
- return ExprError();
+ if (result.isInvalid()) return ExprError();
E = result.get();
}
// C++ [conv.lval]p1:
// A glvalue of a non-function, non-array type T can be
// converted to a prvalue.
- if (!E->isGLValue())
- return E;
+ if (!E->isGLValue()) return E;
QualType T = E->getType();
assert(!T.isNull() && "r-value conversion on typeless expression?");
@@ -721,15 +723,16 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) {
if (getLangOpts().OpenCL &&
!getOpenCLOptions().isAvailableOption("cl_khr_fp16", getLangOpts()) &&
T->isHalfType()) {
- Diag(E->getExprLoc(), diag::err_opencl_half_load_store) << 0 << T;
+ Diag(E->getExprLoc(), diag::err_opencl_half_load_store)
+ << 0 << T;
return ExprError();
}
CheckForNullPointerDereference(*this, E);
if (const ObjCIsaExpr *OISA = dyn_cast<ObjCIsaExpr>(E->IgnoreParenCasts())) {
- NamedDecl *ObjectGetClass =
- LookupSingleName(TUScope, &Context.Idents.get("object_getClass"),
- SourceLocation(), LookupOrdinaryName);
+ NamedDecl *ObjectGetClass = LookupSingleName(TUScope,
+ &Context.Idents.get("object_getClass"),
+ SourceLocation(), LookupOrdinaryName);
if (ObjectGetClass)
Diag(E->getExprLoc(), diag::warn_objc_isa_use)
<< FixItHint::CreateInsertion(OISA->getBeginLoc(), "object_getClass(")
@@ -737,9 +740,10 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) {
SourceRange(OISA->getOpLoc(), OISA->getIsaMemberLoc()), ")");
else
Diag(E->getExprLoc(), diag::warn_objc_isa_use);
- } else if (const ObjCIvarRefExpr *OIRE =
- dyn_cast<ObjCIvarRefExpr>(E->IgnoreParenCasts()))
- DiagnoseDirectIsaAccess(*this, OIRE, SourceLocation(), /* Expr*/ nullptr);
+ }
+ else if (const ObjCIvarRefExpr *OIRE =
+ dyn_cast<ObjCIvarRefExpr>(E->IgnoreParenCasts()))
+ DiagnoseDirectIsaAccess(*this, OIRE, SourceLocation(), /* Expr*/nullptr);
// C++ [conv.lval]p1:
// [...] If T is a non-class type, the type of the prvalue is the
@@ -763,8 +767,8 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) {
return Res;
E = Res.get();
- // Loading a __weak object implicitly retains the value, so we need a cleanup
- // to balance that.
+ // Loading a __weak object implicitly retains the value, so we need a cleanup to
+ // balance that.
if (E->getType().getObjCLifetime() == Qualifiers::OCL_Weak)
Cleanup.setExprNeedsCleanups(true);
@@ -973,8 +977,8 @@ ExprResult Sema::DefaultArgumentPromotion(Expr *E) {
// potentially potentially evaluated contexts.
if (getLangOpts().CPlusPlus && E->isGLValue() && !isUnevaluatedContext()) {
ExprResult Temp = PerformCopyInitialization(
- InitializedEntity::InitializeTemporary(E->getType()), E->getExprLoc(),
- E);
+ InitializedEntity::InitializeTemporary(E->getType()),
+ E->getExprLoc(), E);
if (Temp.isInvalid())
return ExprError();
E = Temp.get();
@@ -1170,10 +1174,8 @@ static bool handleComplexIntegerToFloatConversion(Sema &S, ExprResult &IntExpr,
QualType IntTy,
QualType ComplexTy,
bool SkipCast) {
- if (IntTy->isComplexType() || IntTy->isRealFloatingType())
- return true;
- if (SkipCast)
- return false;
+ if (IntTy->isComplexType() || IntTy->isRealFloatingType()) return true;
+ if (SkipCast) return false;
if (IntTy->isIntegerType()) {
QualType fpTy = ComplexTy->castAs<ComplexType>()->getElementType();
IntExpr = S.ImpCastExprToType(IntExpr.get(), fpTy, CK_IntegralToFloating);
@@ -1249,8 +1251,8 @@ static QualType handleIntToFloatConversion(Sema &S, ExprResult &FloatExpr,
if (IntTy->isIntegerType()) {
if (ConvertInt)
// Convert intExpr to the lhs floating point type.
- IntExpr =
- S.ImpCastExprToType(IntExpr.get(), FloatTy, CK_IntegralToFloating);
+ IntExpr = S.ImpCastExprToType(IntExpr.get(), FloatTy,
+ CK_IntegralToFloating);
return FloatTy;
}
@@ -1265,17 +1267,17 @@ static QualType handleIntToFloatConversion(Sema &S, ExprResult &FloatExpr,
// float -> _Complex float
if (ConvertFloat)
- FloatExpr =
- S.ImpCastExprToType(FloatExpr.get(), result, CK_FloatingRealToComplex);
+ FloatExpr = S.ImpCastExprToType(FloatExpr.get(), result,
+ CK_FloatingRealToComplex);
return result;
}
/// Handle arithmethic conversion with floating point types. Helper
/// function of UsualArithmeticConversions()
-static QualType handleFloatConversion(Sema &S, ExprResult &LHS, ExprResult &RHS,
- QualType LHSType, QualType RHSType,
- bool IsCompAssign) {
+static QualType handleFloatConversion(Sema &S, ExprResult &LHS,
+ ExprResult &RHS, QualType LHSType,
+ QualType RHSType, bool IsCompAssign) {
bool LHSFloat = LHSType->isRealFloatingType();
bool RHSFloat = RHSType->isRealFloatingType();
@@ -1312,11 +1314,11 @@ static QualType handleFloatConversion(Sema &S, ExprResult &LHS, ExprResult &RHS,
return handleIntToFloatConversion(S, LHS, RHS, LHSType, RHSType,
/*ConvertFloat=*/!IsCompAssign,
- /*ConvertInt=*/true);
+ /*ConvertInt=*/ true);
}
assert(RHSFloat);
return handleIntToFloatConversion(S, RHS, LHS, RHSType, LHSType,
- /*ConvertFloat=*/true,
+ /*ConvertFloat=*/ true,
/*ConvertInt=*/!IsCompAssign);
}
@@ -1361,7 +1363,7 @@ ExprResult doComplexIntegralCast(Sema &S, Expr *op, QualType toType) {
return S.ImpCastExprToType(op, S.Context.getComplexType(toType),
CK_IntegralComplexCast);
}
-} // namespace
+}
/// Handle integer arithmetic conversions. Helper function of
/// UsualArithmeticConversions()
@@ -1406,7 +1408,7 @@ static QualType handleIntegerConversion(Sema &S, ExprResult &LHS,
// on most 32-bit systems). Use the unsigned type corresponding
// to the signed type.
QualType result =
- S.Context.getCorrespondingUnsignedType(LHSSigned ? LHSType : RHSType);
+ S.Context.getCorrespondingUnsignedType(LHSSigned ? LHSType : RHSType);
RHS = (*doRHSCast)(S, RHS.get(), result);
if (!IsCompAssign)
LHS = (*doLHSCast)(S, LHS.get(), result);
@@ -1427,8 +1429,8 @@ static QualType handleComplexIntConversion(Sema &S, ExprResult &LHS,
QualType LHSEltType = LHSComplexInt->getElementType();
QualType RHSEltType = RHSComplexInt->getElementType();
QualType ScalarType =
- handleIntegerConversion<doComplexIntegralCast, doComplexIntegralCast>(
- S, LHS, RHS, LHSEltType, RHSEltType, IsCompAssign);
+ handleIntegerConversion<doComplexIntegralCast, doComplexIntegralCast>
+ (S, LHS, RHS, LHSEltType, RHSEltType, IsCompAssign);
return S.Context.getComplexType(ScalarType);
}
@@ -1436,10 +1438,11 @@ static QualType handleComplexIntConversion(Sema &S, ExprResult &LHS,
if (LHSComplexInt) {
QualType LHSEltType = LHSComplexInt->getElementType();
QualType ScalarType =
- handleIntegerConversion<doComplexIntegralCast, doIntegralCast>(
- S, LHS, RHS, LHSEltType, RHSType, IsCompAssign);
+ handleIntegerConversion<doComplexIntegralCast, doIntegralCast>
+ (S, LHS, RHS, LHSEltType, RHSType, IsCompAssign);
QualType ComplexType = S.Context.getComplexType(ScalarType);
- RHS = S.ImpCastExprToType(RHS.get(), ComplexType, CK_IntegralRealToComplex);
+ RHS = S.ImpCastExprToType(RHS.get(), ComplexType,
+ CK_IntegralRealToComplex);
return ComplexType;
}
@@ -1448,12 +1451,13 @@ static QualType handleComplexIntConversion(Sema &S, ExprResult &LHS,
QualType RHSEltType = RHSComplexInt->getElementType();
QualType ScalarType =
- handleIntegerConversion<doIntegralCast, doComplexIntegralCast>(
- S, LHS, RHS, LHSType, RHSEltType, IsCompAssign);
+ handleIntegerConversion<doIntegralCast, doComplexIntegralCast>
+ (S, LHS, RHS, LHSType, RHSEltType, IsCompAssign);
QualType ComplexType = S.Context.getComplexType(ScalarType);
if (!IsCompAssign)
- LHS = S.ImpCastExprToType(LHS.get(), ComplexType, CK_IntegralRealToComplex);
+ LHS = S.ImpCastExprToType(LHS.get(), ComplexType,
+ CK_IntegralRealToComplex);
return ComplexType;
}
@@ -1828,6 +1832,7 @@ QualType Sema::UsualArithmeticConversions(ExprResult &LHS, ExprResult &RHS,
// Semantic Analysis for various Expression Types
//===----------------------------------------------------------------------===//
+
ExprResult Sema::ActOnGenericSelectionExpr(
SourceLocation KeyLoc, SourceLocation DefaultLoc, SourceLocation RParenLoc,
bool PredicateIsExpr, void *ControllingExprOrType,
@@ -1835,10 +1840,10 @@ ExprResult Sema::ActOnGenericSelectionExpr(
unsigned NumAssocs = ArgTypes.size();
assert(NumAssocs == ArgExprs.size());
- TypeSourceInfo **Types = new TypeSourceInfo *[NumAssocs];
+ TypeSourceInfo **Types = new TypeSourceInfo*[NumAssocs];
for (unsigned i = 0; i < NumAssocs; ++i) {
if (ArgTypes[i])
- (void)GetTypeFromParser(ArgTypes[i], &Types[i]);
+ (void) GetTypeFromParser(ArgTypes[i], &Types[i]);
else
Types[i] = nullptr;
}
@@ -1856,7 +1861,7 @@ ExprResult Sema::ActOnGenericSelectionExpr(
ExprResult ER = CreateGenericSelectionExpr(
KeyLoc, DefaultLoc, RParenLoc, PredicateIsExpr, ControllingExprOrType,
llvm::ArrayRef(Types, NumAssocs), ArgExprs);
- delete[] Types;
+ delete [] Types;
return ER;
}
@@ -2005,17 +2010,19 @@ ExprResult Sema::CreateGenericSelectionExpr(
// C11 6.5.1.1p2 "No two generic associations in the same generic
// selection shall specify compatible types."
- for (unsigned j = i + 1; j < NumAssocs; ++j)
+ for (unsigned j = i+1; j < NumAssocs; ++j)
if (Types[j] && !Types[j]->getType()->isDependentType() &&
areTypesCompatibleForGeneric(Context, Types[i]->getType(),
Types[j]->getType())) {
Diag(Types[j]->getTypeLoc().getBeginLoc(),
diag::err_assoc_compatible_types)
- << Types[j]->getTypeLoc().getSourceRange()
- << Types[j]->getType() << Types[i]->getType();
- Diag(Types[i]->getTypeLoc().getBeginLoc(), diag::note_compat_assoc)
- << Types[i]->getTypeLoc().getSourceRange()
- << Types[i]->getType();
+ << Types[j]->getTypeLoc().getSourceRange()
+ << Types[j]->getType()
+ << Types[i]->getType();
+ Diag(Types[i]->getTypeLoc().getBeginLoc(),
+ diag::note_compat_assoc)
+ << Types[i]->getTypeLoc().getSourceRange()
+ << Types[i]->getType();
TypeErrorFound = true;
}
}
@@ -2084,8 +2091,10 @@ ExprResult Sema::CreateGenericSelectionExpr(
Diag(SR.getBegin(), diag::err_generic_sel_multi_match)
<< SR << P.second << (unsigned)CompatIndices.size();
for (unsigned I : CompatIndices) {
- Diag(Types[I]->getTypeLoc().getBeginLoc(), diag::note_compat_assoc)
- << Types[I]->getTypeLoc().getSourceRange() << Types[I]->getType();
+ Diag(Types[I]->getTypeLoc().getBeginLoc(),
+ diag::note_compat_assoc)
+ << Types[I]->getTypeLoc().getSourceRange()
+ << Types[I]->getType();
}
return ExprError();
}
@@ -2106,7 +2115,8 @@ ExprResult Sema::CreateGenericSelectionExpr(
// then the result expression of the generic selection is the expression
// in that generic association. Otherwise, the result expression of the
// generic selection is the expression in the default generic association."
- unsigned ResultIndex = CompatIndices.size() ? CompatIndices[0] : DefaultIndex;
+ unsigned ResultIndex =
+ CompatIndices.size() ? CompatIndices[0] : DefaultIndex;
if (ControllingExpr) {
return GenericSelectionExpr::Create(
@@ -2180,7 +2190,7 @@ static SourceLocation getUDSuffixLoc(Sema &S, SourceLocation TokLoc,
static ExprResult BuildCookedLiteralOperatorCall(Sema &S, Scope *Scope,
IdentifierInfo *UDSuffix,
SourceLocation UDSuffixLoc,
- ArrayRef<Expr *> Args,
+ ArrayRef<Expr*> Args,
SourceLocation LitEndLoc) {
assert(Args.size() <= 2 && "too many arguments for literal operator");
@@ -2192,7 +2202,7 @@ static ExprResult BuildCookedLiteralOperatorCall(Sema &S, Scope *Scope,
}
DeclarationName OpName =
- S.Context.DeclarationNames.getCXXLiteralOperatorName(UDSuffix);
+ S.Context.DeclarationNames.getCXXLiteralOperatorName(UDSuffix);
DeclarationNameInfo OpNameInfo(OpName, UDSuffixLoc);
OpNameInfo.setCXXLiteralOperatorNameLoc(UDSuffixLoc);
@@ -2284,8 +2294,8 @@ Sema::ExpandFunctionLocalPredefinedMacros(ArrayRef<Token> Toks) {
return ExpandedToks;
}
-ExprResult Sema::ActOnStringLiteral(ArrayRef<Token> StringToks,
- Scope *UDLScope) {
+ExprResult
+Sema::ActOnStringLiteral(ArrayRef<Token> StringToks, Scope *UDLScope) {
assert(!StringToks.empty() && "Must have at least one string!");
// StringToks needs backing storage as it doesn't hold array elements itself
@@ -2366,8 +2376,8 @@ ExprResult Sema::ActOnStringLiteral(ArrayRef<Token> StringToks,
// We're building a user-defined literal.
IdentifierInfo *UDSuffix = &Context.Idents.get(Literal.getUDSuffix());
SourceLocation UDSuffixLoc =
- getUDSuffixLoc(*this, StringTokLocs[Literal.getUDSuffixToken()],
- Literal.getUDSuffixOffset());
+ getUDSuffixLoc(*this, StringTokLocs[Literal.getUDSuffixToken()],
+ Literal.getUDSuffixOffset());
// Make sure we're allowed user-defined literals here.
if (!UDLScope)
@@ -2378,11 +2388,13 @@ ExprResult Sema::ActOnStringLiteral(ArrayRef<Token> StringToks,
QualType SizeType = Context.getSizeType();
DeclarationName OpName =
- Context.DeclarationNames.getCXXLiteralOperatorName(UDSuffix);
+ Context.DeclarationNames.getCXXLiteralOperatorName(UDSuffix);
DeclarationNameInfo OpNameInfo(OpName, UDSuffixLoc);
OpNameInfo.setCXXLiteralOperatorNameLoc(UDSuffixLoc);
- QualType ArgTy[] = {Context.getArrayDecayedType(StrTy), SizeType};
+ QualType ArgTy[] = {
+ Context.getArrayDecayedType(StrTy), SizeType
+ };
LookupResult R(*this, OpName, UDSuffixLoc, LookupOrdinaryName);
switch (LookupLiteralOperator(UDLScope, R, ArgTy,
@@ -2392,9 +2404,9 @@ ExprResult Sema::ActOnStringLiteral(ArrayRef<Token> StringToks,
case LOLR_Cooked: {
llvm::APInt Len(Context.getIntWidth(SizeType), Literal.GetNumStringChars());
- IntegerLiteral *LenArg =
- IntegerLiteral::Create(Context, Len, SizeType, StringTokLocs[0]);
- Expr *Args[] = {Lit, LenArg};
+ IntegerLiteral *LenArg = IntegerLiteral::Create(Context, Len, SizeType,
+ StringTokLocs[0]);
+ Expr *Args[] = { Lit, LenArg };
return BuildLiteralOperatorCall(R, OpNameInfo, Args, StringTokLocs.back());
}
@@ -2416,8 +2428,7 @@ ExprResult Sema::ActOnStringLiteral(ArrayRef<Token> StringToks,
llvm::APSInt Value(CharBits, CharIsUnsigned);
TemplateArgument TypeArg(CharTy);
- TemplateArgumentLocInfo TypeArgInfo(
- Context.getTrivialTypeSourceInfo(CharTy));
+ TemplateArgumentLocInfo TypeArgInfo(Context.getTrivialTypeSourceInfo(CharTy));
ExplicitArgs.addArgument(TemplateArgumentLoc(TypeArg, TypeArgInfo));
SourceLocation Loc = StringTokLocs.back();
@@ -2438,9 +2449,10 @@ ExprResult Sema::ActOnStringLiteral(ArrayRef<Token> StringToks,
llvm_unreachable("unexpected literal operator lookup result");
}
-DeclRefExpr *Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
- SourceLocation Loc,
- const CXXScopeSpec *SS) {
+DeclRefExpr *
+Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
+ SourceLocation Loc,
+ const CXXScopeSpec *SS) {
DeclarationNameInfo NameInfo(D->getDeclName(), Loc);
return BuildDeclRefExpr(D, Ty, VK, NameInfo, SS);
}
@@ -2604,10 +2616,11 @@ static bool diagnoseFunctionLikeMacro(Sema &SemaRef, DeclarationName Name,
return false;
}
-void Sema::DecomposeUnqualifiedId(
- const UnqualifiedId &Id, TemplateArgumentListInfo &Buffer,
- DeclarationNameInfo &NameInfo,
- const TemplateArgumentListInfo *&TemplateArgs) {
+void
+Sema::DecomposeUnqualifiedId(const UnqualifiedId &Id,
+ TemplateArgumentListInfo &Buffer,
+ DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *&TemplateArgs) {
if (Id.getKind() == UnqualifiedIdKind::IK_TemplateId) {
Buffer.setLAngleLoc(Id.TemplateId->LAngleLoc);
Buffer.setRAngleLoc(Id.TemplateId->RAngleLoc);
@@ -2764,14 +2777,15 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
OverloadCandidateSet::CSK_Normal);
OverloadCandidateSet::iterator Best;
for (NamedDecl *CD : Corrected) {
- if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(CD))
- AddTemplateOverloadCandidate(FTD,
- DeclAccessPair::make(FTD, AS_none),
- ExplicitTemplateArgs, Args, OCS);
+ if (FunctionTemplateDecl *FTD =
+ dyn_cast<FunctionTemplateDecl>(CD))
+ AddTemplateOverloadCandidate(
+ FTD, DeclAccessPair::make(FTD, AS_none), ExplicitTemplateArgs,
+ Args, OCS);
else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(CD))
if (!ExplicitTemplateArgs || ExplicitTemplateArgs->size() == 0)
- AddOverloadCandidate(FD, DeclAccessPair::make(FD, AS_none), Args,
- OCS);
+ AddOverloadCandidate(FD, DeclAccessPair::make(FD, AS_none),
+ Args, OCS);
}
switch (OCS.BestViableFunction(*this, R.getNameLoc(), Best)) {
case OR_Success:
@@ -2789,8 +2803,8 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
CXXRecordDecl *Record =
Corrected.getCorrectionSpecifier().getAsRecordDecl();
if (!Record)
- Record =
- cast<CXXRecordDecl>(ND->getDeclContext()->getRedeclContext());
+ Record = cast<CXXRecordDecl>(
+ ND->getDeclContext()->getRedeclContext());
R.setNamingClass(Record);
}
@@ -3002,8 +3016,7 @@ ExprResult Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
if (R.empty() && HasTrailingLParen && II &&
getLangOpts().implicitFunctionsAllowed()) {
NamedDecl *D = ImplicitlyDefineFunction(NameLoc, *II, S);
- if (D)
- R.addDecl(D);
+ if (D) R.addDecl(D);
}
// Determine whether this name might be a candidate for
@@ -3129,7 +3142,7 @@ ExprResult Sema::BuildQualifiedDeclarationNameExpr(
if (CD->isInvalidDecl() || CD->isBeingDefined())
return ExprError();
Diag(NameInfo.getLoc(), diag::err_no_member)
- << NameInfo.getName() << DC << SS.getRange();
+ << NameInfo.getName() << DC << SS.getRange();
return ExprError();
}
@@ -3294,15 +3307,14 @@ ExprResult Sema::PerformObjectMemberConversion(Expr *From,
// Otherwise build the appropriate casts.
if (IsDerivedFrom(FromLoc, FromRecordType, QRecordType)) {
CXXCastPath BasePath;
- if (CheckDerivedToBaseConversion(FromRecordType, QRecordType, FromLoc,
- FromRange, &BasePath))
+ if (CheckDerivedToBaseConversion(FromRecordType, QRecordType,
+ FromLoc, FromRange, &BasePath))
return ExprError();
if (PointerConversions)
QType = Context.getPointerType(QType);
- From = ImpCastExprToType(From, QType, CK_UncheckedDerivedToBase, VK,
- &BasePath)
- .get();
+ From = ImpCastExprToType(From, QType, CK_UncheckedDerivedToBase,
+ VK, &BasePath).get();
FromType = QType;
FromRecordType = QRecordType;
@@ -3315,8 +3327,8 @@ ExprResult Sema::PerformObjectMemberConversion(Expr *From,
}
CXXCastPath BasePath;
- if (CheckDerivedToBaseConversion(FromRecordType, DestRecordType, FromLoc,
- FromRange, &BasePath,
+ if (CheckDerivedToBaseConversion(FromRecordType, DestRecordType,
+ FromLoc, FromRange, &BasePath,
/*IgnoreAccess=*/true))
return ExprError();
@@ -3382,6 +3394,7 @@ bool Sema::UseArgumentDependentLookup(const CXXScopeSpec &SS,
return true;
}
+
/// Diagnoses obvious problems with the use of the given declaration
/// as an expression. This is only actually called for lookups that
/// were not overloaded, and it doesn't promise that the declaration
@@ -3787,7 +3800,7 @@ ExprResult Sema::ActOnCharacterConstant(const Token &Tok, Scope *UDLScope) {
else if (Literal.isUTF32())
Ty = Context.Char32Ty; // U'x' -> char32_t in C11 and C++11.
else if (!getLangOpts().CPlusPlus || Literal.isMultiChar())
- Ty = Context.IntTy; // 'x' -> int in C, 'wxyz' -> int in C++.
+ Ty = Context.IntTy; // 'x' -> int in C, 'wxyz' -> int in C++.
else
Ty = Context.CharTy; // 'x' -> char in C++;
// u8'x' -> char in C11-C17 and in C++ without char8_t.
@@ -3802,8 +3815,8 @@ ExprResult Sema::ActOnCharacterConstant(const Token &Tok, Scope *UDLScope) {
else if (Literal.isUTF8())
Kind = CharacterLiteralKind::UTF8;
- Expr *Lit = new (Context)
- CharacterLiteral(Literal.getValue(), Kind, Ty, Tok.getLocation());
+ Expr *Lit = new (Context) CharacterLiteral(Literal.getValue(), Kind, Ty,
+ Tok.getLocation());
if (Literal.getUDSuffix().empty())
return Lit;
@@ -3811,7 +3824,7 @@ ExprResult Sema::ActOnCharacterConstant(const Token &Tok, Scope *UDLScope) {
// We're building a user-defined literal.
IdentifierInfo *UDSuffix = &Context.Idents.get(Literal.getUDSuffix());
SourceLocation UDSuffixLoc =
- getUDSuffixLoc(*this, Tok.getLocation(), Literal.getUDSuffixOffset());
+ getUDSuffixLoc(*this, Tok.getLocation(), Literal.getUDSuffixOffset());
// Make sure we're allowed user-defined literals here.
if (!UDLScope)
@@ -3942,7 +3955,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
// We're building a user-defined literal.
const IdentifierInfo *UDSuffix = &Context.Idents.get(Literal.getUDSuffix());
SourceLocation UDSuffixLoc =
- getUDSuffixLoc(*this, Tok.getLocation(), Literal.getUDSuffixOffset());
+ getUDSuffixLoc(*this, Tok.getLocation(), Literal.getUDSuffixOffset());
// Make sure we're allowed user-defined literals here.
if (!UDLScope)
@@ -3962,7 +3975,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
}
DeclarationName OpName =
- Context.DeclarationNames.getCXXLiteralOperatorName(UDSuffix);
+ Context.DeclarationNames.getCXXLiteralOperatorName(UDSuffix);
DeclarationNameInfo OpNameInfo(OpName, UDSuffixLoc);
OpNameInfo.setCXXLiteralOperatorNameLoc(UDSuffixLoc);
@@ -4056,8 +4069,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
}
}
- if (Literal.isUnsigned)
- Ty = Context.getCorrespondingUnsignedType(Ty);
+ if (Literal.isUnsigned) Ty = Context.getCorrespondingUnsignedType(Ty);
bool isSigned = !Literal.isUnsigned;
unsigned scale = Context.getFixedPointScale(Ty);
@@ -4081,7 +4093,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
Tok.getLocation(), scale);
} else if (Literal.isFloatingLiteral()) {
QualType Ty;
- if (Literal.isHalf) {
+ if (Literal.isHalf){
if (getLangOpts().HLSL ||
getOpenCLOptions().isAvailableOption("cl_khr_fp16", getLangOpts()))
Ty = Context.HalfTy;
@@ -4256,7 +4268,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
// Does it fit in a unsigned int?
if (ResultVal.isIntN(IntSize)) {
// Does it fit in a signed int?
- if (!Literal.isUnsigned && ResultVal[IntSize - 1] == 0)
+ if (!Literal.isUnsigned && ResultVal[IntSize-1] == 0)
Ty = Context.IntTy;
else if (AllowUnsigned)
Ty = Context.UnsignedIntTy;
@@ -4271,7 +4283,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
// Does it fit in a unsigned long?
if (ResultVal.isIntN(LongSize)) {
// Does it fit in a signed long?
- if (!Literal.isUnsigned && ResultVal[LongSize - 1] == 0)
+ if (!Literal.isUnsigned && ResultVal[LongSize-1] == 0)
Ty = Context.LongTy;
else if (AllowUnsigned)
Ty = Context.UnsignedLongTy;
@@ -4304,9 +4316,8 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
// Does it fit in a signed long long?
// To be compatible with MSVC, hex integer literals ending with the
// LL or i64 suffix are always signed in Microsoft mode.
- if (!Literal.isUnsigned &&
- (ResultVal[LongLongSize - 1] == 0 ||
- (getLangOpts().MSVCCompat && Literal.isLongLong)))
+ if (!Literal.isUnsigned && (ResultVal[LongLongSize-1] == 0 ||
+ (getLangOpts().MSVCCompat && Literal.isLongLong)))
Ty = Context.LongLongTy;
else if (AllowUnsigned)
Ty = Context.UnsignedLongLongTy;
@@ -4345,8 +4356,8 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
// If this is an imaginary literal, create the ImaginaryLiteral wrapper.
if (Literal.isImaginary) {
- Res = new (Context)
- ImaginaryLiteral(Res, Context.getComplexType(Res->getType()));
+ Res = new (Context) ImaginaryLiteral(Res,
+ Context.getComplexType(Res->getType()));
// In C++, this is a GNU extension. In C, it's a C2y extension.
if (getLangOpts().CPlusPlus)
@@ -4374,7 +4385,8 @@ static bool CheckVecStepTraitOperandType(Sema &S, QualType T,
// Every built-in scalar type (OpenCL 1.1 6.1.1) is either an arithmetic
// type (C99 6.2.5p18) or void.
if (!(T->isArithmeticType() || T->isVoidType() || T->isVectorType())) {
- S.Diag(Loc, diag::err_vecstep_non_scalar_vector_type) << T << ArgRange;
+ S.Diag(Loc, diag::err_vecstep_non_scalar_vector_type)
+ << T << ArgRange;
return true;
}
@@ -4457,7 +4469,8 @@ static bool CheckObjCTraitOperandConstraints(Sema &S, QualType T,
// runtime doesn't allow it.
if (!S.LangOpts.ObjCRuntime.allowsSizeofAlignof() && T->isObjCObjectType()) {
S.Diag(Loc, diag::err_sizeof_nonfragile_interface)
- << T << (TraitKind == UETT_SizeOf) << ArgRange;
+ << T << (TraitKind == UETT_SizeOf)
+ << ArgRange;
return true;
}
@@ -4477,9 +4490,9 @@ static void warnOnSizeofOnArrayDecay(Sema &S, SourceLocation Loc, QualType T,
if (!ICE || ICE->getCastKind() != CK_ArrayToPointerDecay)
return;
- S.Diag(Loc, diag::warn_sizeof_array_decay)
- << ICE->getSourceRange() << ICE->getType()
- << ICE->getSubExpr()->getType();
+ S.Diag(Loc, diag::warn_sizeof_array_decay) << ICE->getSourceRange()
+ << ICE->getType()
+ << ICE->getSubExpr()->getType();
}
bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E,
@@ -4504,7 +4517,8 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E,
// used to build SFINAE gadgets.
// FIXME: Should we consider instantiation-dependent operands to 'alignof'?
if (IsUnevaluatedOperand && !inTemplateInstantiation() &&
- !E->isInstantiationDependent() && !E->getType()->isVariableArrayType() &&
+ !E->isInstantiationDependent() &&
+ !E->getType()->isVariableArrayType() &&
E->HasSideEffects(Context, false))
Diag(E->getExprLoc(), diag::warn_side_effects_unevaluated_context);
@@ -4582,7 +4596,8 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E,
QualType OType = PVD->getOriginalType();
QualType Type = PVD->getType();
if (Type->isPointerType() && OType->isArrayType()) {
- Diag(E->getExprLoc(), diag::warn_sizeof_array_param) << Type << OType;
+ Diag(E->getExprLoc(), diag::warn_sizeof_array_param)
+ << Type << OType;
Diag(PVD->getLocation(), diag::note_declared_at);
}
}
@@ -4609,7 +4624,7 @@ static bool CheckAlignOfExpr(Sema &S, Expr *E, UnaryExprOrTypeTrait ExprKind) {
if (E->getObjectKind() == OK_BitField) {
S.Diag(E->getExprLoc(), diag::err_sizeof_alignof_typeof_bitfield)
- << 1 << E->getSourceRange();
+ << 1 << E->getSourceRange();
return true;
}
@@ -4643,7 +4658,7 @@ static bool CheckAlignOfExpr(Sema &S, Expr *E, UnaryExprOrTypeTrait ExprKind) {
// definition if we can find a member of it.
if (!FD->getParent()->isCompleteDefinition()) {
S.Diag(E->getExprLoc(), diag::err_alignof_member_of_incomplete_type)
- << E->getSourceRange();
+ << E->getSourceRange();
return true;
}
@@ -4926,8 +4941,9 @@ ExprResult Sema::CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo,
ExprKind, TInfo, Context.getSizeType(), OpLoc, R.getEnd());
}
-ExprResult Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc,
- UnaryExprOrTypeTrait ExprKind) {
+ExprResult
+Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc,
+ UnaryExprOrTypeTrait ExprKind) {
ExprResult PE = CheckPlaceholderExpr(E);
if (PE.isInvalid())
return ExprError();
@@ -4943,9 +4959,9 @@ ExprResult Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc,
} else if (ExprKind == UETT_VecStep) {
isInvalid = CheckVecStepExpr(E);
} else if (ExprKind == UETT_OpenMPRequiredSimdAlign) {
- Diag(E->getExprLoc(), diag::err_openmp_default_simd_align_expr);
- isInvalid = true;
- } else if (E->refersToBitField()) { // C99 6.5.3.4p1.
+ Diag(E->getExprLoc(), diag::err_openmp_default_simd_align_expr);
+ isInvalid = true;
+ } else if (E->refersToBitField()) { // C99 6.5.3.4p1.
Diag(E->getExprLoc(), diag::err_sizeof_alignof_typeof_bitfield) << 0;
isInvalid = true;
} else if (ExprKind == UETT_VectorElements || ExprKind == UETT_SizeOf ||
@@ -4959,8 +4975,7 @@ ExprResult Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc,
if ((ExprKind == UETT_SizeOf || ExprKind == UETT_CountOf) &&
E->getType()->isVariableArrayType()) {
PE = TransformToPotentiallyEvaluated(E);
- if (PE.isInvalid())
- return ExprError();
+ if (PE.isInvalid()) return ExprError();
E = PE.get();
}
@@ -4969,17 +4984,16 @@ ExprResult Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc,
ExprKind, E, Context.getSizeType(), OpLoc, E->getSourceRange().getEnd());
}
-ExprResult Sema::ActOnUnaryExprOrTypeTraitExpr(SourceLocation OpLoc,
- UnaryExprOrTypeTrait ExprKind,
- bool IsType, void *TyOrEx,
- SourceRange ArgRange) {
+ExprResult
+Sema::ActOnUnaryExprOrTypeTraitExpr(SourceLocation OpLoc,
+ UnaryExprOrTypeTrait ExprKind, bool IsType,
+ void *TyOrEx, SourceRange ArgRange) {
// If error parsing type, ignore.
- if (!TyOrEx)
- return ExprError();
+ if (!TyOrEx) return ExprError();
if (IsType) {
TypeSourceInfo *TInfo;
- (void)GetTypeFromParser(ParsedType::getFromOpaquePtr(TyOrEx), &TInfo);
+ (void) GetTypeFromParser(ParsedType::getFromOpaquePtr(TyOrEx), &TInfo);
return CreateUnaryExprOrTypeTraitExpr(TInfo, OpLoc, ExprKind, ArgRange);
}
@@ -5026,37 +5040,33 @@ static QualType CheckRealImagOperand(Sema &S, ExprResult &V, SourceLocation Loc,
// Test for placeholders.
ExprResult PR = S.CheckPlaceholderExpr(V.get());
- if (PR.isInvalid())
- return QualType();
+ if (PR.isInvalid()) return QualType();
if (PR.get() != V.get()) {
V = PR;
return CheckRealImagOperand(S, V, Loc, IsReal);
}
// Reject anything else.
- S.Diag(Loc, diag::err_realimag_invalid_type)
- << V.get()->getType() << (IsReal ? "__real" : "__imag");
+ S.Diag(Loc, diag::err_realimag_invalid_type) << V.get()->getType()
+ << (IsReal ? "__real" : "__imag");
return QualType();
}
-ExprResult Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
- tok::TokenKind Kind, Expr *Input) {
+
+
+ExprResult
+Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
+ tok::TokenKind Kind, Expr *Input) {
UnaryOperatorKind Opc;
switch (Kind) {
- default:
- llvm_unreachable("Unknown unary op!");
- case tok::plusplus:
- Opc = UO_PostInc;
- break;
- case tok::minusminus:
- Opc = UO_PostDec;
- break;
+ default: llvm_unreachable("Unknown unary op!");
+ case tok::plusplus: Opc = UO_PostInc; break;
+ case tok::minusminus: Opc = UO_PostDec; break;
}
// Since this might is a postfix expression, get rid of ParenListExprs.
ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Input);
- if (Result.isInvalid())
- return ExprError();
+ if (Result.isInvalid()) return ExprError();
Input = Result.get();
return BuildUnaryOp(S, OpLoc, Opc, Input);
@@ -5065,7 +5075,8 @@ ExprResult Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
/// Diagnose if arithmetic on the given ObjC pointer is illegal.
///
/// \return true on error
-static bool checkArithmeticOnObjCPointer(Sema &S, SourceLocation opLoc,
+static bool checkArithmeticOnObjCPointer(Sema &S,
+ SourceLocation opLoc,
Expr *op) {
assert(op->getType()->isObjCObjectPointerType());
if (S.LangOpts.ObjCRuntime.allowsPointerArithmetic() &&
@@ -5073,8 +5084,8 @@ static bool checkArithmeticOnObjCPointer(Sema &S, SourceLocation opLoc,
return false;
S.Diag(opLoc, diag::err_arithmetic_nonfragile_interface)
- << op->getType()->castAs<ObjCObjectPointerType>()->getPointeeType()
- << op->getSourceRange();
+ << op->getType()->castAs<ObjCObjectPointerType>()->getPointeeType()
+ << op->getSourceRange();
return true;
}
@@ -5480,9 +5491,9 @@ void Sema::CheckSubscriptAccessOfNoDeref(const ArraySubscriptExpr *E) {
}
}
-ExprResult Sema::CreateBuiltinArraySubscriptExpr(Expr *Base,
- SourceLocation LLoc, Expr *Idx,
- SourceLocation RLoc) {
+ExprResult
+Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
+ Expr *Idx, SourceLocation RLoc) {
Expr *LHSExp = Base;
Expr *RHSExp = Idx;
@@ -5529,7 +5540,7 @@ ExprResult Sema::CreateBuiltinArraySubscriptExpr(Expr *Base,
IndexExpr = RHSExp;
ResultType = PTy->getPointeeType();
} else if (const ObjCObjectPointerType *PTy =
- LHSTy->getAs<ObjCObjectPointerType>()) {
+ LHSTy->getAs<ObjCObjectPointerType>()) {
BaseExpr = LHSExp;
IndexExpr = RHSExp;
@@ -5541,19 +5552,19 @@ ExprResult Sema::CreateBuiltinArraySubscriptExpr(Expr *Base,
ResultType = PTy->getPointeeType();
} else if (const PointerType *PTy = RHSTy->getAs<PointerType>()) {
- // Handle the uncommon case of "123[Ptr]".
+ // Handle the uncommon case of "123[Ptr]".
BaseExpr = RHSExp;
IndexExpr = LHSExp;
ResultType = PTy->getPointeeType();
} else if (const ObjCObjectPointerType *PTy =
- RHSTy->getAs<ObjCObjectPointerType>()) {
- // Handle the uncommon case of "123[Ptr]".
+ RHSTy->getAs<ObjCObjectPointerType>()) {
+ // Handle the uncommon case of "123[Ptr]".
BaseExpr = RHSExp;
IndexExpr = LHSExp;
ResultType = PTy->getPointeeType();
if (!LangOpts.isSubscriptPointerArithmetic()) {
Diag(LLoc, diag::err_subscript_nonfragile_interface)
- << ResultType << BaseExpr->getSourceRange();
+ << ResultType << BaseExpr->getSourceRange();
return ExprError();
}
} else if (LHSTy->isSubscriptableVectorType()) {
@@ -5597,8 +5608,7 @@ ExprResult Sema::CreateBuiltinArraySubscriptExpr(Expr *Base,
Diag(LHSExp->getBeginLoc(), diag::ext_subscript_non_lvalue)
<< LHSExp->getSourceRange();
LHSExp = ImpCastExprToType(LHSExp, Context.getArrayDecayedType(LHSTy),
- CK_ArrayToPointerDecay)
- .get();
+ CK_ArrayToPointerDecay).get();
LHSTy = LHSExp->getType();
BaseExpr = LHSExp;
@@ -5609,8 +5619,7 @@ ExprResult Sema::CreateBuiltinArraySubscriptExpr(Expr *Base,
Diag(RHSExp->getBeginLoc(), diag::ext_subscript_non_lvalue)
<< RHSExp->getSourceRange();
RHSExp = ImpCastExprToType(RHSExp, Context.getArrayDecayedType(RHSTy),
- CK_ArrayToPointerDecay)
- .get();
+ CK_ArrayToPointerDecay).get();
RHSTy = RHSExp->getType();
BaseExpr = RHSExp;
@@ -5618,7 +5627,7 @@ ExprResult Sema::CreateBuiltinArraySubscriptExpr(Expr *Base,
ResultType = RHSTy->castAs<PointerType>()->getPointeeType();
} else {
return ExprError(Diag(LLoc, diag::err_typecheck_subscript_value)
- << LHSExp->getSourceRange() << RHSExp->getSourceRange());
+ << LHSExp->getSourceRange() << RHSExp->getSourceRange());
}
// C99 6.5.2.1p1
if (!IndexExpr->getType()->isIntegerType() && !IndexExpr->isTypeDependent())
@@ -5647,7 +5656,8 @@ ExprResult Sema::CreateBuiltinArraySubscriptExpr(Expr *Base,
if (ResultType->isVoidType() && !getLangOpts().CPlusPlus) {
// GNU extension: subscripting on pointer to void
- Diag(LLoc, diag::ext_gnu_subscript_void_type) << BaseExpr->getSourceRange();
+ Diag(LLoc, diag::ext_gnu_subscript_void_type)
+ << BaseExpr->getSourceRange();
// C forbids expressions of unqualified void type from being l-values.
// See IsCForbiddenLValueType.
@@ -6113,7 +6123,7 @@ class FunctionCallCCC final : public FunctionCallFilterCCC {
private:
const IdentifierInfo *const FunctionName;
};
-} // namespace
+}
static TypoCorrection TryTypoCorrectionForCall(Sema &S, Expr *Fn,
FunctionDecl *FDecl,
@@ -6173,12 +6183,13 @@ static bool isParenthetizedAndQualifiedAddressOfExpr(Expr *Fn) {
return false;
}
-bool Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
- FunctionDecl *FDecl,
- const FunctionProtoType *Proto,
- ArrayRef<Expr *> Args,
- SourceLocation RParenLoc,
- bool IsExecConfig) {
+bool
+Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
+ FunctionDecl *FDecl,
+ const FunctionProtoType *Proto,
+ ArrayRef<Expr *> Args,
+ SourceLocation RParenLoc,
+ bool IsExecConfig) {
// Bail out early if calling a builtin with custom typechecking.
// For HLSL builtin aliases, argument conversion is still needed because
// overload resolution may have selected a conversion sequence (e.g.,
@@ -6201,9 +6212,9 @@ bool Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
bool Invalid = false;
unsigned MinArgs = FDecl ? FDecl->getMinRequiredArguments() : NumParams;
unsigned FnKind = Fn->getType()->isBlockPointerType()
- ? 1 /* block */
- : (IsExecConfig ? 3 /* kernel function (exec config) */
- : 0 /* function */);
+ ? 1 /* block */
+ : (IsExecConfig ? 3 /* kernel function (exec config) */
+ : 0 /* function */);
// If too few arguments are available (and we don't have default
// arguments for the remaining parameters), don't make the call.
@@ -6342,12 +6353,12 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl,
// Strip the unbridged-cast placeholder expression off, if applicable.
bool CFAudited = false;
- if (Arg->getType() == Context.ARCUnbridgedCastTy && FDecl &&
- FDecl->hasAttr<CFAuditedTransferAttr>() &&
+ if (Arg->getType() == Context.ARCUnbridgedCastTy &&
+ FDecl && FDecl->hasAttr<CFAuditedTransferAttr>() &&
(!Param || !Param->hasAttr<CFConsumedAttr>()))
Arg = ObjC().stripARCUnbridgedCast(Arg);
- else if (getLangOpts().ObjCAutoRefCount && FDecl &&
- FDecl->hasAttr<CFAuditedTransferAttr>() &&
+ else if (getLangOpts().ObjCAutoRefCount &&
+ FDecl && FDecl->hasAttr<CFAuditedTransferAttr>() &&
(!Param || !Param->hasAttr<CFConsumedAttr>()))
CFAudited = true;
@@ -6425,7 +6436,7 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl,
AllArgs.push_back(arg.get());
}
- // Otherwise do argument promotion, (C99 6.5.2.2p7).
+ // Otherwise do argument promotion, (C99 6.5.2.2p7).
} else {
for (Expr *A : Args.slice(ArgIx)) {
ExprResult Arg = DefaultVariadicArgumentPromotion(A, CallType, FDecl);
@@ -6447,11 +6458,13 @@ static void DiagnoseCalleeStaticArrayParam(Sema &S, ParmVarDecl *PVD) {
TL = DTL.getOriginalLoc();
if (ArrayTypeLoc ATL = TL.getAs<ArrayTypeLoc>())
S.Diag(PVD->getLocation(), diag::note_callee_static_array)
- << ATL.getLocalSourceRange();
+ << ATL.getLocalSourceRange();
}
-void Sema::CheckStaticArrayArgument(SourceLocation CallLoc, ParmVarDecl *Param,
- const Expr *ArgExpr) {
+void
+Sema::CheckStaticArrayArgument(SourceLocation CallLoc,
+ ParmVarDecl *Param,
+ const Expr *ArgExpr) {
// Static array parameters are not supported in C++.
if (!Param || getLangOpts().CPlusPlus)
return;
@@ -6462,7 +6475,8 @@ void Sema::CheckStaticArrayArgument(SourceLocation CallLoc, ParmVarDecl *Param,
if (!AT || AT->getSizeModifier() != ArraySizeModifier::Static)
return;
- if (ArgExpr->isNullPointerConstant(Context, Expr::NPC_NeverValueDependent)) {
+ if (ArgExpr->isNullPointerConstant(Context,
+ Expr::NPC_NeverValueDependent)) {
Diag(CallLoc, diag::warn_null_arg) << ArgExpr->getSourceRange();
DiagnoseCalleeStaticArrayParam(*this, Param);
return;
@@ -6473,7 +6487,7 @@ void Sema::CheckStaticArrayArgument(SourceLocation CallLoc, ParmVarDecl *Param,
return;
const ConstantArrayType *ArgCAT =
- Context.getAsConstantArrayType(ArgExpr->IgnoreParenCasts()->getType());
+ Context.getAsConstantArrayType(ArgExpr->IgnoreParenCasts()->getType());
if (!ArgCAT)
return;
@@ -6509,21 +6523,23 @@ static ExprResult rebuildUnknownAnyFunction(Sema &S, Expr *fn);
static bool isPlaceholderToRemoveAsArg(QualType type) {
// Placeholders are never sugared.
const BuiltinType *placeholder = dyn_cast<BuiltinType>(type);
- if (!placeholder)
- return false;
+ if (!placeholder) return false;
switch (placeholder->getKind()) {
- // Ignore all the non-placeholder types.
-#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
+ // Ignore all the non-placeholder types.
+#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
case BuiltinType::Id:
#include "clang/Basic/OpenCLImageTypes.def"
-#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) case BuiltinType::Id:
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
+ case BuiltinType::Id:
#include "clang/Basic/OpenCLExtensionTypes.def"
- // In practice we'll never use this, since all SVE types are sugared
- // via TypedefTypes rather than exposed directly as BuiltinTypes.
-#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+ // In practice we'll never use this, since all SVE types are sugared
+ // via TypedefTypes rather than exposed directly as BuiltinTypes.
+#define SVE_TYPE(Name, Id, SingletonId) \
+ case BuiltinType::Id:
#include "clang/Basic/AArch64ACLETypes.def"
-#define PPC_VECTOR_TYPE(Name, Id, Size) case BuiltinType::Id:
+#define PPC_VECTOR_TYPE(Name, Id, Size) \
+ case BuiltinType::Id:
#include "clang/Basic/PPCTypes.def"
#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
#include "clang/Basic/RISCVVTypes.def"
@@ -6568,6 +6584,7 @@ static bool isPlaceholderToRemoveAsArg(QualType type) {
case BuiltinType::OMPArrayShaping:
case BuiltinType::OMPIterator:
return true;
+
}
llvm_unreachable("bad builtin type kind");
}
@@ -6579,10 +6596,8 @@ bool Sema::CheckArgsForPlaceholders(MultiExprArg args) {
for (size_t i = 0, e = args.size(); i != e; i++) {
if (isPlaceholderToRemoveAsArg(args[i]->getType())) {
ExprResult result = CheckPlaceholderExpr(args[i]);
- if (result.isInvalid())
- hasInvalid = true;
- else
- args[i] = result.get();
+ if (result.isInvalid()) hasInvalid = true;
+ else args[i] = result.get();
}
}
return hasInvalid;
@@ -6653,8 +6668,8 @@ static FunctionDecl *rewriteBuiltinFunctionDecl(Sema *Sema, ASTContext &Context,
FunctionProtoType::ExtProtoInfo EPI;
EPI.Variadic = FT->isVariadic();
- QualType OverloadTy =
- Context.getFunctionType(FT->getReturnType(), OverloadParams, EPI);
+ QualType OverloadTy = Context.getFunctionType(FT->getReturnType(),
+ OverloadParams, EPI);
DeclContext *Parent = FDecl->getParent();
FunctionDecl *OverloadDecl = FunctionDecl::Create(
Context, Parent, FDecl->getLocation(), FDecl->getLocation(),
@@ -6662,14 +6677,14 @@ static FunctionDecl *rewriteBuiltinFunctionDecl(Sema *Sema, ASTContext &Context,
/*TInfo=*/nullptr, SC_Extern, Sema->getCurFPFeatures().isFPConstrained(),
false,
/*hasPrototype=*/true);
- SmallVector<ParmVarDecl *, 16> Params;
+ SmallVector<ParmVarDecl*, 16> Params;
FT = cast<FunctionProtoType>(OverloadTy);
for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
QualType ParamType = FT->getParamType(i);
ParmVarDecl *Parm =
ParmVarDecl::Create(Context, OverloadDecl, SourceLocation(),
- SourceLocation(), nullptr, ParamType,
- /*TInfo=*/nullptr, SC_None, nullptr);
+ SourceLocation(), nullptr, ParamType,
+ /*TInfo=*/nullptr, SC_None, nullptr);
Parm->setScopeInfo(0, i);
Params.push_back(Parm);
}
@@ -6775,6 +6790,7 @@ tryImplicitlyCaptureThisIfImplicitMemberFunctionAccessWithDependentArgs(
if (!enclosingClassIsRelatedToClassInWhichMembersWereFound(UME, S))
return;
+
DeclContext *EnclosingFunctionCtx = S.CurContext->getParent()->getParent();
// If the enclosing function is not dependent, then this lambda is
// capture ready, so if we can capture this, do so.
@@ -6883,8 +6899,7 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
bool AllowRecovery) {
// Since this might be a postfix expression, get rid of ParenListExprs.
ExprResult Result = MaybeConvertParenListExprToParenExpr(Scope, Fn);
- if (Result.isInvalid())
- return ExprError();
+ if (Result.isInvalid()) return ExprError();
Fn = Result.get();
// The __builtin_amdgcn_is_invocable builtin is special, and will be resolved
@@ -6929,8 +6944,7 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
}
if (Fn->getType() == Context.PseudoObjectTy) {
ExprResult result = CheckPlaceholderExpr(Fn);
- if (result.isInvalid())
- return ExprError();
+ if (result.isInvalid()) return ExprError();
Fn = result.get();
}
@@ -6968,8 +6982,7 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
if (Fn->getType() == Context.UnknownAnyTy) {
ExprResult result = rebuildUnknownAnyFunction(*this, Fn);
- if (result.isInvalid())
- return ExprError();
+ if (result.isInvalid()) return ExprError();
Fn = result.get();
}
@@ -7003,8 +7016,7 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
// If we're directly calling a function, get the appropriate declaration.
if (Fn->getType() == Context.UnknownAnyTy) {
ExprResult result = rebuildUnknownAnyFunction(*this, Fn);
- if (result.isInvalid())
- return ExprError();
+ if (result.isInvalid()) return ExprError();
Fn = result.get();
}
@@ -7063,7 +7075,7 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
// type.
if (getLangOpts().HIP && FD && FD->getBuiltinID()) {
for (unsigned Idx = 0; Idx < ArgExprs.size() && Idx < FD->param_size();
- ++Idx) {
+ ++Idx) {
ParmVarDecl *Param = FD->getParamDecl(Idx);
if (!ArgExprs[Idx] || !Param || !Param->getType()->isPointerType() ||
!ArgExprs[Idx]->getType()->isPointerType())
@@ -7076,14 +7088,10 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
// Add address space cast if target address spaces are different
bool NeedImplicitASC =
- ParamAS != LangAS::Default && // Pointer params in generic AS don't
- // need special handling.
- (ArgAS ==
- LangAS::Default || // We do allow implicit conversion from
- // generic AS or from specific AS which has
- // target AS matching that of Param.
- getASTContext().getTargetAddressSpace(ArgAS) ==
- getASTContext().getTargetAddressSpace(ParamAS));
+ ParamAS != LangAS::Default && // Pointer params in generic AS don't need special handling.
+ ( ArgAS == LangAS::Default || // We do allow implicit conversion from generic AS
+ // or from specific AS which has target AS matching that of Param.
+ getASTContext().getTargetAddressSpace(ArgAS) == getASTContext().getTargetAddressSpace(ParamAS));
if (!NeedImplicitASC)
continue;
@@ -7100,8 +7108,9 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
ArgPtQuals.setAddressSpace(ParamAS);
auto NewArgPtTy =
Context.getQualifiedType(ArgPtTy.getUnqualifiedType(), ArgPtQuals);
- auto NewArgTy = Context.getQualifiedType(
- Context.getPointerType(NewArgPtTy), ArgTy.getQualifiers());
+ auto NewArgTy =
+ Context.getQualifiedType(Context.getPointerType(NewArgPtTy),
+ ArgTy.getQualifiers());
// Finally perform an implicit address space cast
ArgExprs[Idx] = ImpCastExprToType(ArgExprs[Idx], NewArgTy,
@@ -7340,8 +7349,7 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
if (Config) {
// CUDA: Kernel calls must be to global functions
if (FDecl && !FDecl->hasAttr<CUDAGlobalAttr>())
- return ExprError(
- Diag(LParenLoc, diag::err_kern_call_not_global_function)
+ return ExprError(Diag(LParenLoc,diag::err_kern_call_not_global_function)
<< FDecl << Fn->getSourceRange());
// CUDA: Kernel function must have 'void' return type
@@ -7349,12 +7357,12 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
!FuncT->getReturnType()->getAs<AutoType>() &&
!FuncT->getReturnType()->isInstantiationDependentType())
return ExprError(Diag(LParenLoc, diag::err_kern_type_not_void_return)
- << Fn->getType() << Fn->getSourceRange());
+ << Fn->getType() << Fn->getSourceRange());
} else {
// CUDA: Calls to global functions must be configured
if (FDecl && FDecl->hasAttr<CUDAGlobalAttr>())
return ExprError(Diag(LParenLoc, diag::err_global_call_not_config)
- << FDecl << Fn->getSourceRange());
+ << FDecl << Fn->getSourceRange());
}
}
@@ -7396,11 +7404,9 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
const FunctionDecl *Def = nullptr;
if (FDecl->hasBody(Def) && Args.size() != Def->param_size()) {
Proto = Def->getType()->getAs<FunctionProtoType>();
- if (!Proto ||
- !(Proto->isVariadic() && Args.size() >= Def->param_size()))
+ if (!Proto || !(Proto->isVariadic() && Args.size() >= Def->param_size()))
Diag(RParenLoc, diag::warn_call_wrong_number_of_arguments)
- << (Args.size() > Def->param_size()) << FDecl
- << Fn->getSourceRange();
+ << (Args.size() > Def->param_size()) << FDecl << Fn->getSourceRange();
}
// If the function we're calling isn't a function prototype, but we have
@@ -7750,7 +7756,7 @@ ExprResult Sema::BuildCompoundLiteralExpr(
// "If the compound literal occurs inside the body of a function, the
// type name shall not be qualified by an address-space qualifier."
Diag(LParenLoc, diag::err_compound_literal_with_address_space)
- << SourceRange(LParenLoc, LiteralExpr->getSourceRange().getEnd());
+ << SourceRange(LParenLoc, LiteralExpr->getSourceRange().getEnd());
return ExprError();
}
@@ -7800,9 +7806,9 @@ ExprResult Sema::BuildCompoundLiteralExpr(
return MaybeBindToTemporary(E);
}
-ExprResult Sema::ActOnInitList(SourceLocation LBraceLoc,
- MultiExprArg InitArgList,
- SourceLocation RBraceLoc) {
+ExprResult
+Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList,
+ SourceLocation RBraceLoc) {
// Only produce each kind of designated initialization diagnostic once.
SourceLocation FirstDesignator;
bool DiagnosedArrayDesignator = false;
@@ -7822,14 +7828,14 @@ ExprResult Sema::ActOnInitList(SourceLocation LBraceLoc,
if (!DiagnosedNestedDesignator && DIE->size() > 1) {
DiagnosedNestedDesignator = true;
Diag(DIE->getBeginLoc(), diag::ext_designated_init_nested)
- << DIE->getDesignatorsSourceRange();
+ << DIE->getDesignatorsSourceRange();
}
for (auto &Desig : DIE->designators()) {
if (!Desig.isFieldDesignator() && !DiagnosedArrayDesignator) {
DiagnosedArrayDesignator = true;
Diag(Desig.getBeginLoc(), diag::ext_designated_init_array)
- << Desig.getSourceRange();
+ << Desig.getSourceRange();
}
}
@@ -7837,18 +7843,18 @@ ExprResult Sema::ActOnInitList(SourceLocation LBraceLoc,
!isa<DesignatedInitExpr>(InitArgList[0])) {
DiagnosedMixedDesignator = true;
Diag(DIE->getBeginLoc(), diag::ext_designated_init_mixed)
- << DIE->getSourceRange();
+ << DIE->getSourceRange();
Diag(InitArgList[0]->getBeginLoc(), diag::note_designated_init_mixed)
- << InitArgList[0]->getSourceRange();
+ << InitArgList[0]->getSourceRange();
}
} else if (getLangOpts().CPlusPlus && !DiagnosedMixedDesignator &&
isa<DesignatedInitExpr>(InitArgList[0])) {
DiagnosedMixedDesignator = true;
auto *DIE = cast<DesignatedInitExpr>(InitArgList[0]);
Diag(DIE->getBeginLoc(), diag::ext_designated_init_mixed)
- << DIE->getSourceRange();
+ << DIE->getSourceRange();
Diag(InitArgList[I]->getBeginLoc(), diag::note_designated_init_mixed)
- << InitArgList[I]->getSourceRange();
+ << InitArgList[I]->getSourceRange();
}
}
@@ -7882,8 +7888,7 @@ ExprResult Sema::BuildInitList(SourceLocation LBraceLoc,
// Ignore failures; dropping the entire initializer list because
// of one failure would be terrible for indexing/etc.
- if (result.isInvalid())
- continue;
+ if (result.isInvalid()) continue;
InitArgList[I] = result.get();
}
@@ -7900,8 +7905,7 @@ void Sema::maybeExtendBlockObject(ExprResult &E) {
assert(E.get()->isPRValue());
// Only do this in an r-value context.
- if (!getLangOpts().ObjCAutoRefCount)
- return;
+ if (!getLangOpts().ObjCAutoRefCount) return;
E = ImplicitCastExpr::Create(
Context, E.get()->getType(), CK_ARCExtendBlockObject, E.get(),
@@ -7937,8 +7941,7 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) {
}
case Type::STK_BlockPointer:
return (SrcKind == Type::STK_BlockPointer
- ? CK_BitCast
- : CK_AnyPointerToBlockPointerCast);
+ ? CK_BitCast : CK_AnyPointerToBlockPointerCast);
case Type::STK_ObjCObjectPointer:
if (SrcKind == Type::STK_ObjCObjectPointer)
return CK_BitCast;
@@ -8001,13 +8004,13 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) {
return CK_IntegralToFloating;
case Type::STK_IntegralComplex:
Src = ImpCastExprToType(Src.get(),
- DestTy->castAs<ComplexType>()->getElementType(),
- CK_IntegralCast);
+ DestTy->castAs<ComplexType>()->getElementType(),
+ CK_IntegralCast);
return CK_IntegralRealToComplex;
case Type::STK_FloatingComplex:
Src = ImpCastExprToType(Src.get(),
- DestTy->castAs<ComplexType>()->getElementType(),
- CK_IntegralToFloating);
+ DestTy->castAs<ComplexType>()->getElementType(),
+ CK_IntegralToFloating);
return CK_FloatingRealToComplex;
case Type::STK_MemberPointer:
llvm_unreachable("member pointer type in C");
@@ -8129,8 +8132,7 @@ static bool breakDownVectorType(QualType type, uint64_t &len,
// We allow lax conversion to and from non-vector types, but only if
// they're real types (i.e. non-complex, non-pointer scalar types).
- if (!type->isRealType())
- return false;
+ if (!type->isRealType()) return false;
len = 1;
eltType = type;
@@ -8213,10 +8215,8 @@ bool Sema::areLaxCompatibleVectorTypes(QualType srcTy, QualType destTy) {
// depend on them). Most scalar OP ExtVector cases are handled by the
// splat path anyway, which does what we want (convert, not bitcast).
// What this rules out for ExtVectors is crazy things like char4*float.
- if (srcTy->isScalarType() && destTy->isExtVectorType())
- return false;
- if (destTy->isScalarType() && srcTy->isExtVectorType())
- return false;
+ if (srcTy->isScalarType() && destTy->isExtVectorType()) return false;
+ if (destTy->isScalarType() && srcTy->isExtVectorType()) return false;
return areVectorTypesSameSize(srcTy, destTy);
}
@@ -8242,7 +8242,7 @@ bool Sema::isLaxVectorConversion(QualType srcTy, QualType destTy) {
// OK, integer (vector) -> integer (vector) bitcast.
break;
- case LangOptions::LaxVectorConversionKind::All:
+ case LangOptions::LaxVectorConversionKind::All:
break;
}
@@ -8277,14 +8277,14 @@ bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty,
if (Ty->isVectorType() || Ty->isIntegralType(Context)) {
if (!areLaxCompatibleVectorTypes(Ty, VectorTy))
return Diag(R.getBegin(),
- Ty->isVectorType()
- ? diag::err_invalid_conversion_between_vectors
- : diag::err_invalid_conversion_between_vector_and_integer)
- << VectorTy << Ty << R;
+ Ty->isVectorType() ?
+ diag::err_invalid_conversion_between_vectors :
+ diag::err_invalid_conversion_between_vector_and_integer)
+ << VectorTy << Ty << R;
} else
return Diag(R.getBegin(),
diag::err_invalid_conversion_between_vector_and_scalar)
- << VectorTy << Ty << R;
+ << VectorTy << Ty << R;
Kind = CK_BitCast;
return false;
@@ -8356,8 +8356,8 @@ ExprResult Sema::CheckExtVectorCast(SourceRange R, QualType DestTy,
(getLangOpts().OpenCL &&
!Context.hasSameUnqualifiedType(DestTy, SrcTy) &&
!Context.areCompatibleVectorTypes(DestTy, SrcTy))) {
- Diag(R.getBegin(), diag::err_invalid_conversion_between_ext_vectors)
- << DestTy << SrcTy << R;
+ Diag(R.getBegin(),diag::err_invalid_conversion_between_ext_vectors)
+ << DestTy << SrcTy << R;
return ExprError();
}
Kind = CK_BitCast;
@@ -8370,7 +8370,7 @@ ExprResult Sema::CheckExtVectorCast(SourceRange R, QualType DestTy,
if (SrcTy->isPointerType())
return Diag(R.getBegin(),
diag::err_invalid_conversion_between_vector_and_scalar)
- << DestTy << SrcTy << R;
+ << DestTy << SrcTy << R;
Kind = CK_VectorSplat;
return prepareVectorSplat(DestTy, CastExpr);
@@ -8411,9 +8411,10 @@ static void CheckSufficientAllocSize(Sema &S, QualType DestType,
<< Size.getQuantity() << TargetType << LhsSize->getQuantity();
}
-ExprResult Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc,
- Declarator &D, ParsedType &Ty,
- SourceLocation RParenLoc, Expr *CastExpr) {
+ExprResult
+Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc,
+ Declarator &D, ParsedType &Ty,
+ SourceLocation RParenLoc, Expr *CastExpr) {
assert(!D.isInvalidType() && (CastExpr != nullptr) &&
"ActOnCastExpr(): missing type or expr");
@@ -8437,9 +8438,8 @@ ExprResult Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc,
// i.e. all the elements are integer constants.
ParenExpr *PE = dyn_cast<ParenExpr>(CastExpr);
ParenListExpr *PLE = dyn_cast<ParenListExpr>(CastExpr);
- if ((getLangOpts().AltiVec || getLangOpts().ZVector ||
- getLangOpts().OpenCL) &&
- castType->isVectorType() && (PE || PLE)) {
+ if ((getLangOpts().AltiVec || getLangOpts().ZVector || getLangOpts().OpenCL)
+ && castType->isVectorType() && (PE || PLE)) {
if (PLE && PLE->getNumExprs() == 0) {
Diag(PLE->getExprLoc(), diag::err_altivec_empty_initializer);
return ExprError();
@@ -8448,7 +8448,8 @@ ExprResult Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc,
Expr *E = (PE ? PE->getSubExpr() : PLE->getExpr(0));
if (!E->isTypeDependent() && !E->getType()->isVectorType())
isVectorLiteral = true;
- } else
+ }
+ else
isVectorLiteral = true;
}
@@ -8462,8 +8463,7 @@ ExprResult Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc,
// sequence of BinOp comma operators.
if (isa<ParenListExpr>(CastExpr)) {
ExprResult Result = MaybeConvertParenListExprToParenExpr(S, CastExpr);
- if (Result.isInvalid())
- return ExprError();
+ if (Result.isInvalid()) return ExprError();
CastExpr = Result.get();
}
@@ -8530,12 +8530,16 @@ ExprResult Sema::BuildVectorLiteral(SourceLocation LParenLoc,
Literal = ImpCastExprToType(Literal.get(), ElemTy,
PrepareScalarCast(Literal, ElemTy));
return BuildCStyleCastExpr(LParenLoc, TInfo, RParenLoc, Literal.get());
- } else if (numExprs < numElems) {
- Diag(E->getExprLoc(), diag::err_incorrect_number_of_vector_initializers);
+ }
+ else if (numExprs < numElems) {
+ Diag(E->getExprLoc(),
+ diag::err_incorrect_number_of_vector_initializers);
return ExprError();
- } else
+ }
+ else
initExprs.append(exprs, exprs + numExprs);
- } else {
+ }
+ else {
// For OpenCL, when the number of initializers is a single value,
// it will be replicated to all components of the vector.
if (getLangOpts().OpenCL && VTy->getVectorKind() == VectorKind::Generic &&
@@ -8567,8 +8571,8 @@ ExprResult Sema::BuildVectorLiteral(SourceLocation LParenLoc,
return BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc, initE);
}
-ExprResult Sema::MaybeConvertParenListExprToParenExpr(Scope *S,
- Expr *OrigExpr) {
+ExprResult
+Sema::MaybeConvertParenListExprToParenExpr(Scope *S, Expr *OrigExpr) {
ParenListExpr *E = dyn_cast<ParenListExpr>(OrigExpr);
if (!E)
return OrigExpr;
@@ -8576,16 +8580,16 @@ ExprResult Sema::MaybeConvertParenListExprToParenExpr(Scope *S,
ExprResult Result(E->getExpr(0));
for (unsigned i = 1, e = E->getNumExprs(); i != e && !Result.isInvalid(); ++i)
- Result =
- ActOnBinOp(S, E->getExprLoc(), tok::comma, Result.get(), E->getExpr(i));
+ Result = ActOnBinOp(S, E->getExprLoc(), tok::comma, Result.get(),
+ E->getExpr(i));
- if (Result.isInvalid())
- return ExprError();
+ if (Result.isInvalid()) return ExprError();
return ActOnParenExpr(E->getLParenLoc(), E->getRParenLoc(), Result.get());
}
-ExprResult Sema::ActOnParenListExpr(SourceLocation L, SourceLocation R,
+ExprResult Sema::ActOnParenListExpr(SourceLocation L,
+ SourceLocation R,
MultiExprArg Val) {
return ParenListExpr::Create(Context, L, Val, R);
}
@@ -8603,14 +8607,16 @@ bool Sema::DiagnoseConditionalForNull(const Expr *LHSExpr, const Expr *RHSExpr,
SourceLocation QuestionLoc) {
const Expr *NullExpr = LHSExpr;
const Expr *NonPointerExpr = RHSExpr;
- Expr::NullPointerConstantKind NullKind = NullExpr->isNullPointerConstant(
- Context, Expr::NPC_ValueDependentIsNotNull);
+ Expr::NullPointerConstantKind NullKind =
+ NullExpr->isNullPointerConstant(Context,
+ Expr::NPC_ValueDependentIsNotNull);
if (NullKind == Expr::NPCK_NotNull) {
NullExpr = RHSExpr;
NonPointerExpr = LHSExpr;
- NullKind = NullExpr->isNullPointerConstant(
- Context, Expr::NPC_ValueDependentIsNotNull);
+ NullKind =
+ NullExpr->isNullPointerConstant(Context,
+ Expr::NPC_ValueDependentIsNotNull);
}
if (NullKind == Expr::NPCK_NotNull)
@@ -8643,16 +8649,15 @@ static bool checkCondition(Sema &S, const Expr *Cond,
// OpenCL v1.1 s6.3.i says the condition cannot be a floating point type.
if (S.getLangOpts().OpenCL && CondTy->isFloatingType()) {
S.Diag(QuestionLoc, diag::err_typecheck_cond_expect_nonfloat)
- << CondTy << Cond->getSourceRange();
+ << CondTy << Cond->getSourceRange();
return true;
}
// C99 6.5.15p2
- if (CondTy->isScalarType())
- return false;
+ if (CondTy->isScalarType()) return false;
S.Diag(QuestionLoc, diag::err_typecheck_cond_expect_scalar)
- << CondTy << Cond->getSourceRange();
+ << CondTy << Cond->getSourceRange();
return true;
}
@@ -8662,7 +8667,7 @@ static bool checkConditionalNullPointer(Sema &S, ExprResult &NullExpr,
QualType PointerTy) {
if ((!PointerTy->isAnyPointerType() && !PointerTy->isBlockPointerType()) ||
!NullExpr.get()->isNullPointerConstant(S.Context,
- Expr::NPC_ValueDependentIsNull))
+ Expr::NPC_ValueDependentIsNull))
return true;
NullExpr = S.ImpCastExprToType(NullExpr.get(), PointerTy, CK_NullToPointer);
@@ -8724,8 +8729,7 @@ static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS,
return QualType();
}
- unsigned MergedCVRQual =
- lhQual.getCVRQualifiers() | rhQual.getCVRQualifiers();
+ unsigned MergedCVRQual = lhQual.getCVRQualifiers() | rhQual.getCVRQualifiers();
auto LHSCastKind = CK_BitCast, RHSCastKind = CK_BitCast;
lhQual.removeCVRQualifiers();
rhQual.removeCVRQualifiers();
@@ -8825,8 +8829,8 @@ static QualType checkConditionalBlockPointerCompatibility(Sema &S,
return destType;
}
S.Diag(Loc, diag::err_typecheck_cond_incompatible_operands)
- << LHSTy << RHSTy << LHS.get()->getSourceRange()
- << RHS.get()->getSourceRange();
+ << LHSTy << RHSTy << LHS.get()->getSourceRange()
+ << RHS.get()->getSourceRange();
return QualType();
}
@@ -8835,8 +8839,10 @@ static QualType checkConditionalBlockPointerCompatibility(Sema &S,
}
/// Return the resulting type when the operands are both pointers.
-static QualType checkConditionalObjectPointersCompatibility(
- Sema &S, ExprResult &LHS, ExprResult &RHS, SourceLocation Loc) {
+static QualType
+checkConditionalObjectPointersCompatibility(Sema &S, ExprResult &LHS,
+ ExprResult &RHS,
+ SourceLocation Loc) {
// get the pointer types
QualType LHSTy = LHS.get()->getType();
QualType RHSTy = RHS.get()->getType();
@@ -8848,8 +8854,8 @@ static QualType checkConditionalObjectPointersCompatibility(
// ignore qualifiers on void (C99 6.5.15p3, clause 6)
if (lhptee->isVoidType() && rhptee->isIncompleteOrObjectType()) {
// Figure out necessary qualifiers (C99 6.5.15p6)
- QualType destPointee =
- S.Context.getQualifiedType(lhptee, rhptee.getQualifiers());
+ QualType destPointee
+ = S.Context.getQualifiedType(lhptee, rhptee.getQualifiers());
QualType destType = S.Context.getPointerType(destPointee);
// Add qualifiers if necessary.
LHS = S.ImpCastExprToType(LHS.get(), destType, CK_NoOp);
@@ -8858,8 +8864,8 @@ static QualType checkConditionalObjectPointersCompatibility(
return destType;
}
if (rhptee->isVoidType() && lhptee->isIncompleteOrObjectType()) {
- QualType destPointee =
- S.Context.getQualifiedType(rhptee, lhptee.getQualifiers());
+ QualType destPointee
+ = S.Context.getQualifiedType(rhptee, lhptee.getQualifiers());
QualType destType = S.Context.getPointerType(destPointee);
// Add qualifiers if necessary.
RHS = S.ImpCastExprToType(RHS.get(), destType, CK_NoOp);
@@ -8874,7 +8880,7 @@ static QualType checkConditionalObjectPointersCompatibility(
/// Return false if the first expression is not an integer and the second
/// expression is not a pointer, true otherwise.
static bool checkPointerIntegerMismatch(Sema &S, ExprResult &Int,
- Expr *PointerExpr, SourceLocation Loc,
+ Expr* PointerExpr, SourceLocation Loc,
bool IsIntFirstExpr) {
if (!PointerExpr->getType()->isPointerType() ||
!Int.get()->getType()->isIntegerType())
@@ -8884,8 +8890,8 @@ static bool checkPointerIntegerMismatch(Sema &S, ExprResult &Int,
Expr *Expr2 = IsIntFirstExpr ? PointerExpr : Int.get();
S.Diag(Loc, diag::ext_typecheck_cond_pointer_integer_mismatch)
- << Expr1->getType() << Expr2->getType() << Expr1->getSourceRange()
- << Expr2->getSourceRange();
+ << Expr1->getType() << Expr2->getType()
+ << Expr1->getSourceRange() << Expr2->getSourceRange();
Int = S.ImpCastExprToType(Int.get(), PointerExpr->getType(),
CK_IntegralToPointer);
return true;
@@ -8916,19 +8922,19 @@ static QualType OpenCLArithmeticConversions(Sema &S, ExprResult &LHS,
// For conversion purposes, we ignore any qualifiers.
// For example, "const float" and "float" are equivalent.
QualType LHSType =
- S.Context.getCanonicalType(LHS.get()->getType()).getUnqualifiedType();
+ S.Context.getCanonicalType(LHS.get()->getType()).getUnqualifiedType();
QualType RHSType =
- S.Context.getCanonicalType(RHS.get()->getType()).getUnqualifiedType();
+ S.Context.getCanonicalType(RHS.get()->getType()).getUnqualifiedType();
if (!LHSType->isIntegerType() && !LHSType->isRealFloatingType()) {
S.Diag(QuestionLoc, diag::err_typecheck_cond_expect_int_float)
- << LHSType << LHS.get()->getSourceRange();
+ << LHSType << LHS.get()->getSourceRange();
return QualType();
}
if (!RHSType->isIntegerType() && !RHSType->isRealFloatingType()) {
S.Diag(QuestionLoc, diag::err_typecheck_cond_expect_int_float)
- << RHSType << RHS.get()->getSourceRange();
+ << RHSType << RHS.get()->getSourceRange();
return QualType();
}
@@ -8942,8 +8948,8 @@ static QualType OpenCLArithmeticConversions(Sema &S, ExprResult &LHS,
/*IsCompAssign = */ false);
// Finally, we have two differing integer types.
- return handleIntegerConversion<doIntegralCast, doIntegralCast>(
- S, LHS, RHS, LHSType, RHSType, /*IsCompAssign = */ false);
+ return handleIntegerConversion<doIntegralCast, doIntegralCast>
+ (S, LHS, RHS, LHSType, RHSType, /*IsCompAssign = */ false);
}
/// Convert scalar operands to a vector that matches the
@@ -8957,12 +8963,11 @@ static QualType OpenCLArithmeticConversions(Sema &S, ExprResult &LHS,
/// into a vector of that type where the length matches the condition
/// vector type. s6.11.6 requires that the element types of the result
/// and the condition must have the same number of bits.
-static QualType OpenCLConvertScalarsToVectors(Sema &S, ExprResult &LHS,
- ExprResult &RHS, QualType CondTy,
- SourceLocation QuestionLoc) {
+static QualType
+OpenCLConvertScalarsToVectors(Sema &S, ExprResult &LHS, ExprResult &RHS,
+ QualType CondTy, SourceLocation QuestionLoc) {
QualType ResTy = OpenCLArithmeticConversions(S, LHS, RHS, QuestionLoc);
- if (ResTy.isNull())
- return QualType();
+ if (ResTy.isNull()) return QualType();
const VectorType *CV = CondTy->getAs<VectorType>();
assert(CV);
@@ -8972,8 +8977,8 @@ static QualType OpenCLConvertScalarsToVectors(Sema &S, ExprResult &LHS,
QualType VectorTy = S.Context.getExtVectorType(ResTy, NumElements);
// Ensure that all types have the same number of bits
- if (S.Context.getTypeSize(CV->getElementType()) !=
- S.Context.getTypeSize(ResTy)) {
+ if (S.Context.getTypeSize(CV->getElementType())
+ != S.Context.getTypeSize(ResTy)) {
// Since VectorTy is created internally, it does not pretty print
// with an OpenCL name. Instead, we just print a description.
std::string EleTyName = ResTy.getUnqualifiedType().getAsString();
@@ -8981,7 +8986,7 @@ static QualType OpenCLConvertScalarsToVectors(Sema &S, ExprResult &LHS,
llvm::raw_svector_ostream OS(Str);
OS << "(vector of " << NumElements << " '" << EleTyName << "' values)";
S.Diag(QuestionLoc, diag::err_conditional_vector_element_size)
- << CondTy << OS.str();
+ << CondTy << OS.str();
return QualType();
}
@@ -9000,11 +9005,10 @@ static bool checkOpenCLConditionVector(Sema &S, Expr *Cond,
const VectorType *CondTy = Cond->getType()->getAs<VectorType>();
assert(CondTy);
QualType EleTy = CondTy->getElementType();
- if (EleTy->isIntegerType())
- return false;
+ if (EleTy->isIntegerType()) return false;
S.Diag(QuestionLoc, diag::err_typecheck_cond_expect_nonfloat)
- << Cond->getType() << Cond->getSourceRange();
+ << Cond->getType() << Cond->getSourceRange();
return true;
}
@@ -9022,7 +9026,7 @@ static bool checkVectorResult(Sema &S, QualType CondTy, QualType VecResTy,
if (CV->getNumElements() != RV->getNumElements()) {
S.Diag(QuestionLoc, diag::err_conditional_vector_size)
- << CondTy << VecResTy;
+ << CondTy << VecResTy;
return true;
}
@@ -9043,9 +9047,10 @@ static bool checkVectorResult(Sema &S, QualType CondTy, QualType VecResTy,
/// Return the resulting type for the conditional operator in
/// OpenCL (aka "ternary selection operator", OpenCL v1.1
/// s6.3.i) when the condition is a vector type.
-static QualType OpenCLCheckVectorConditional(Sema &S, ExprResult &Cond,
- ExprResult &LHS, ExprResult &RHS,
- SourceLocation QuestionLoc) {
+static QualType
+OpenCLCheckVectorConditional(Sema &S, ExprResult &Cond,
+ ExprResult &LHS, ExprResult &RHS,
+ SourceLocation QuestionLoc) {
Cond = S.DefaultFunctionArrayLvalueConversion(Cond.get());
if (Cond.isInvalid())
return QualType();
@@ -9106,13 +9111,11 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
SourceLocation QuestionLoc) {
ExprResult LHSResult = CheckPlaceholderExpr(LHS.get());
- if (!LHSResult.isUsable())
- return QualType();
+ if (!LHSResult.isUsable()) return QualType();
LHS = LHSResult;
ExprResult RHSResult = CheckPlaceholderExpr(RHS.get());
- if (!RHSResult.isUsable())
- return QualType();
+ if (!RHSResult.isUsable()) return QualType();
RHS = RHSResult;
// C++ is sufficiently different to merit its own checker.
@@ -9171,16 +9174,16 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
// Diagnose attempts to convert between __ibm128, __float128 and long double
// where such conversions currently can't be handled.
if (unsupportedTypeConversion(*this, LHSTy, RHSTy)) {
- Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands)
- << LHSTy << RHSTy << LHS.get()->getSourceRange()
- << RHS.get()->getSourceRange();
+ Diag(QuestionLoc,
+ diag::err_typecheck_cond_incompatible_operands) << LHSTy << RHSTy
+ << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
return QualType();
}
// OpenCL v2.0 s6.12.5 - Blocks cannot be used as expressions of the ternary
// selection operator (?:).
- if (getLangOpts().OpenCL && ((int)checkBlockType(*this, LHS.get()) |
- (int)checkBlockType(*this, RHS.get()))) {
+ if (getLangOpts().OpenCL &&
+ ((int)checkBlockType(*this, LHS.get()) | (int)checkBlockType(*this, RHS.get()))) {
return QualType();
}
@@ -9239,10 +9242,8 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
// C99 6.5.15p6 - "if one operand is a null pointer constant, the result has
// the type of the other operand."
- if (!checkConditionalNullPointer(*this, RHS, LHSTy))
- return LHSTy;
- if (!checkConditionalNullPointer(*this, LHS, RHSTy))
- return RHSTy;
+ if (!checkConditionalNullPointer(*this, RHS, LHSTy)) return LHSTy;
+ if (!checkConditionalNullPointer(*this, LHS, RHSTy)) return RHSTy;
// All objective-c pointer type analysis is done here.
QualType compositeType =
@@ -9252,6 +9253,7 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
if (!compositeType.isNull())
return compositeType;
+
// Handle block pointer types.
if (LHSTy->isBlockPointerType() || RHSTy->isBlockPointerType())
return checkConditionalBlockPointerCompatibility(*this, LHS, RHS,
@@ -9265,10 +9267,10 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
// GCC compatibility: soften pointer/integer mismatch. Note that
// null pointers have been filtered out by this point.
if (checkPointerIntegerMismatch(*this, LHS, RHS.get(), QuestionLoc,
- /*IsIntFirstExpr=*/true))
+ /*IsIntFirstExpr=*/true))
return RHSTy;
if (checkPointerIntegerMismatch(*this, RHS, LHS.get(), QuestionLoc,
- /*IsIntFirstExpr=*/false))
+ /*IsIntFirstExpr=*/false))
return LHSTy;
// Emit a better diagnostic if one of the expressions is a null pointer
@@ -9284,8 +9286,8 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
// Otherwise, the operands are not compatible.
Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands)
- << LHSTy << RHSTy << LHS.get()->getSourceRange()
- << RHS.get()->getSourceRange();
+ << LHSTy << RHSTy << LHS.get()->getSourceRange()
+ << RHS.get()->getSourceRange();
return QualType();
}
@@ -9297,9 +9299,9 @@ static void SuggestParentheses(Sema &Self, SourceLocation Loc,
SourceLocation EndLoc = Self.getLocForEndOfToken(ParenRange.getEnd());
if (ParenRange.getBegin().isFileID() && ParenRange.getEnd().isFileID() &&
EndLoc.isValid()) {
- Self.Diag(Loc, Note) << FixItHint::CreateInsertion(ParenRange.getBegin(),
- "(")
- << FixItHint::CreateInsertion(EndLoc, ")");
+ Self.Diag(Loc, Note)
+ << FixItHint::CreateInsertion(ParenRange.getBegin(), "(")
+ << FixItHint::CreateInsertion(EndLoc, ")");
} else {
// We can't display the parentheses, so just show the bare note.
Self.Diag(Loc, Note) << ParenRange;
@@ -9348,8 +9350,8 @@ static bool IsArithmeticBinaryExpr(const Expr *E, BinaryOperatorKind *Opcode,
// Make sure this is really a binary operator that is safe to pass into
// BinaryOperator::getOverloadedOpcode(), e.g. it's not a subscript op.
OverloadedOperatorKind OO = Call->getOperator();
- if (OO < OO_Plus || OO > OO_Arrow || OO == OO_PlusPlus ||
- OO == OO_MinusMinus)
+ if (OO < OO_Plus || OO > OO_Arrow ||
+ OO == OO_PlusPlus || OO == OO_MinusMinus)
return false;
BinaryOperatorKind OpKind = BinaryOperator::getOverloadedOpcode(OO);
@@ -9405,8 +9407,9 @@ static void DiagnoseConditionalPrecedence(Sema &Self, SourceLocation OpLoc,
? diag::warn_precedence_bitwise_conditional
: diag::warn_precedence_conditional;
- Self.Diag(OpLoc, DiagID) << Condition->getSourceRange()
- << BinaryOperator::getOpcodeStr(CondOpcode);
+ Self.Diag(OpLoc, DiagID)
+ << Condition->getSourceRange()
+ << BinaryOperator::getOpcodeStr(CondOpcode);
SuggestParentheses(
Self, OpLoc,
@@ -9446,7 +9449,7 @@ static QualType computeConditionalNullability(QualType ResTy, bool IsBin,
MergedKind = NullabilityKind::NonNull;
else
MergedKind = RHSKind;
- // Compute nullability of a normal conditional expression.
+ // Compute nullability of a normal conditional expression.
} else {
if (LHSKind == NullabilityKind::Nullable ||
RHSKind == NullabilityKind::Nullable)
@@ -9472,8 +9475,9 @@ static QualType computeConditionalNullability(QualType ResTy, bool IsBin,
}
ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
- SourceLocation ColonLoc, Expr *CondExpr,
- Expr *LHSExpr, Expr *RHSExpr) {
+ SourceLocation ColonLoc,
+ Expr *CondExpr, Expr *LHSExpr,
+ Expr *RHSExpr) {
// If this is the gnu "x ?: y" extension, analyze the types as though the LHS
// was the condition.
OpaqueValueExpr *opaqueValue = nullptr;
@@ -9485,17 +9489,18 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
// as Objective-C++'s dictionary subscripting syntax.
if (commonExpr->hasPlaceholderType()) {
ExprResult result = CheckPlaceholderExpr(commonExpr);
- if (!result.isUsable())
- return ExprError();
+ if (!result.isUsable()) return ExprError();
commonExpr = result.get();
}
// We usually want to apply unary conversions *before* saving, except
// in the special case of a C++ l-value conditional.
- if (!(getLangOpts().CPlusPlus && !commonExpr->isTypeDependent() &&
- commonExpr->getValueKind() == RHSExpr->getValueKind() &&
- commonExpr->isGLValue() && commonExpr->isOrdinaryOrBitFieldObject() &&
- RHSExpr->isOrdinaryOrBitFieldObject() &&
- Context.hasSameType(commonExpr->getType(), RHSExpr->getType()))) {
+ if (!(getLangOpts().CPlusPlus
+ && !commonExpr->isTypeDependent()
+ && commonExpr->getValueKind() == RHSExpr->getValueKind()
+ && commonExpr->isGLValue()
+ && commonExpr->isOrdinaryOrBitFieldObject()
+ && RHSExpr->isOrdinaryOrBitFieldObject()
+ && Context.hasSameType(commonExpr->getType(), RHSExpr->getType()))) {
ExprResult commonRes = UsualUnaryConversions(commonExpr);
if (commonRes.isInvalid())
return ExprError();
@@ -9512,9 +9517,11 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
commonExpr = MatExpr.get();
}
- opaqueValue = new (Context) OpaqueValueExpr(
- commonExpr->getExprLoc(), commonExpr->getType(),
- commonExpr->getValueKind(), commonExpr->getObjectKind(), commonExpr);
+ opaqueValue = new (Context) OpaqueValueExpr(commonExpr->getExprLoc(),
+ commonExpr->getType(),
+ commonExpr->getValueKind(),
+ commonExpr->getObjectKind(),
+ commonExpr);
LHSExpr = CondExpr = opaqueValue;
}
@@ -9522,9 +9529,10 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
ExprValueKind VK = VK_PRValue;
ExprObjectKind OK = OK_Ordinary;
ExprResult Cond = CondExpr, LHS = LHSExpr, RHS = RHSExpr;
- QualType result =
- CheckConditionalOperands(Cond, LHS, RHS, VK, OK, QuestionLoc);
- if (result.isNull() || Cond.isInvalid() || LHS.isInvalid() || RHS.isInvalid())
+ QualType result = CheckConditionalOperands(Cond, LHS, RHS,
+ VK, OK, QuestionLoc);
+ if (result.isNull() || Cond.isInvalid() || LHS.isInvalid() ||
+ RHS.isInvalid())
return ExprError();
DiagnoseConditionalPrecedence(*this, QuestionLoc, Cond.get(), LHS.get(),
@@ -9532,8 +9540,8 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
CheckBoolLikeConversion(Cond.get(), QuestionLoc);
- result =
- computeConditionalNullability(result, commonExpr, LHSTy, RHSTy, Context);
+ result = computeConditionalNullability(result, commonExpr, LHSTy, RHSTy,
+ Context);
if (!commonExpr)
return new (Context)
@@ -9707,9 +9715,9 @@ static AssignConvertType checkPointerTypesForAssignment(Sema &S,
if (isa<PointerType>(lhptee) && isa<PointerType>(rhptee)) {
do {
std::tie(lhptee, lhq) =
- cast<PointerType>(lhptee)->getPointeeType().split().asPair();
+ cast<PointerType>(lhptee)->getPointeeType().split().asPair();
std::tie(rhptee, rhq) =
- cast<PointerType>(rhptee)->getPointeeType().split().asPair();
+ cast<PointerType>(rhptee)->getPointeeType().split().asPair();
// Inconsistent address spaces at this point is invalid, even if the
// address spaces would be compatible.
@@ -10360,7 +10368,8 @@ Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType,
if (RHS.get()->isNullPointerConstant(Context,
Expr::NPC_ValueDependentIsNull)) {
- RHS = ImpCastExprToType(RHS.get(), it->getType(), CK_NullToPointer);
+ RHS = ImpCastExprToType(RHS.get(), it->getType(),
+ CK_NullToPointer);
InitField = it;
break;
}
@@ -10418,12 +10427,13 @@ AssignConvertType Sema::CheckSingleAssignmentConstraints(QualType LHSType,
RHS = PerformImplicitConversion(RHS.get(), LHSType.getUnqualifiedType(),
AssignmentAction::Assigning);
} else {
- ImplicitConversionSequence ICS = TryImplicitConversion(
- RHS.get(), LHSType.getUnqualifiedType(),
- /*SuppressUserConversions=*/false, AllowedExplicit::None,
- /*InOverloadResolution=*/false,
- /*CStyle=*/false,
- /*AllowObjCWritebackConversion=*/false);
+ ImplicitConversionSequence ICS =
+ TryImplicitConversion(RHS.get(), LHSType.getUnqualifiedType(),
+ /*SuppressUserConversions=*/false,
+ AllowedExplicit::None,
+ /*InOverloadResolution=*/false,
+ /*CStyle=*/false,
+ /*AllowObjCWritebackConversion=*/false);
if (ICS.isFailure())
return AssignConvertType::Incompatible;
RHS = PerformImplicitConversion(RHS.get(), LHSType.getUnqualifiedType(),
@@ -10639,27 +10649,27 @@ struct OriginalOperand {
Expr *Orig;
NamedDecl *Conversion;
};
-} // namespace
+}
QualType Sema::InvalidOperands(SourceLocation Loc, ExprResult &LHS,
ExprResult &RHS) {
OriginalOperand OrigLHS(LHS.get()), OrigRHS(RHS.get());
Diag(Loc, diag::err_typecheck_invalid_operands)
- << OrigLHS.getType() << OrigRHS.getType() << LHS.get()->getSourceRange()
- << RHS.get()->getSourceRange();
+ << OrigLHS.getType() << OrigRHS.getType()
+ << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
// If a user-defined conversion was applied to either of the operands prior
// to applying the built-in operator rules, tell the user about it.
if (OrigLHS.Conversion) {
Diag(OrigLHS.Conversion->getLocation(),
diag::note_typecheck_invalid_operands_converted)
- << 0 << LHS.get()->getType();
+ << 0 << LHS.get()->getType();
}
if (OrigRHS.Conversion) {
Diag(OrigRHS.Conversion->getLocation(),
diag::note_typecheck_invalid_operands_converted)
- << 1 << RHS.get()->getType();
+ << 1 << RHS.get()->getType();
}
return QualType();
@@ -10702,8 +10712,10 @@ QualType Sema::InvalidLogicalVectorOperands(SourceLocation Loc, ExprResult &LHS,
/// \param scalar - if non-null, actually perform the conversions
/// \return true if the operation fails (but without diagnosing the failure)
static bool tryVectorConvertAndSplat(Sema &S, ExprResult *scalar,
- QualType scalarTy, QualType vectorEltTy,
- QualType vectorTy, unsigned &DiagID) {
+ QualType scalarTy,
+ QualType vectorEltTy,
+ QualType vectorTy,
+ unsigned &DiagID) {
// The conversion to apply to the scalar before splatting it,
// if necessary.
CastKind scalarCast = CK_NoOp;
@@ -10711,10 +10723,9 @@ static bool tryVectorConvertAndSplat(Sema &S, ExprResult *scalar,
if (vectorEltTy->isBooleanType() && scalarTy->isIntegralType(S.Context)) {
scalarCast = CK_IntegralToBoolean;
} else if (vectorEltTy->isIntegralType(S.Context)) {
- if (S.getLangOpts().OpenCL &&
- (scalarTy->isRealFloatingType() ||
- (scalarTy->isIntegerType() &&
- S.Context.getIntegerTypeOrder(vectorEltTy, scalarTy) < 0))) {
+ if (S.getLangOpts().OpenCL && (scalarTy->isRealFloatingType() ||
+ (scalarTy->isIntegerType() &&
+ S.Context.getIntegerTypeOrder(vectorEltTy, scalarTy) < 0))) {
DiagID = diag::err_opencl_scalar_type_rank_greater_than_vector_type;
return true;
}
@@ -10729,7 +10740,8 @@ static bool tryVectorConvertAndSplat(Sema &S, ExprResult *scalar,
return true;
}
scalarCast = CK_FloatingCast;
- } else if (scalarTy->isIntegralType(S.Context))
+ }
+ else if (scalarTy->isIntegralType(S.Context))
scalarCast = CK_IntegralToFloating;
else
return true;
@@ -11159,11 +11171,11 @@ QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS,
if (!IsCompAssign) {
*OtherExpr = ImpCastExprToType(OtherExpr->get(), VecType, CK_BitCast);
return VecType;
- // In a compound assignment, lhs += rhs, 'lhs' is a lvalue src, forbidding
- // any implicit cast. Here, the 'rhs' should be implicit casted to 'lhs'
- // type. Note that this is already done by non-compound assignments in
- // CheckAssignmentConstraints. If it's a scalar type, only bitcast for
- // <1 x T> -> T. The result is also a vector type.
+ // In a compound assignment, lhs += rhs, 'lhs' is a lvalue src, forbidding
+ // any implicit cast. Here, the 'rhs' should be implicit casted to 'lhs'
+ // type. Note that this is already done by non-compound assignments in
+ // CheckAssignmentConstraints. If it's a scalar type, only bitcast for
+ // <1 x T> -> T. The result is also a vector type.
} else if (OtherType->isExtVectorType() || OtherType->isVectorType() ||
(OtherType->isScalarType() && VT->getNumElements() == 1)) {
ExprResult *RHSExpr = &RHS;
@@ -11178,8 +11190,8 @@ QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS,
if ((!RHSVecType && !RHSType->isRealType()) ||
(!LHSVecType && !LHSType->isRealType())) {
Diag(Loc, diag::err_typecheck_vector_not_convertable_non_scalar)
- << LHSType << RHSType << LHS.get()->getSourceRange()
- << RHS.get()->getSourceRange();
+ << LHSType << RHSType
+ << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
return QualType();
}
@@ -11187,13 +11199,15 @@ QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS,
// If the operands are of more than one vector type, then an error shall
// occur. Implicit conversions between vector types are not permitted, per
// section 6.2.1.
- if (getLangOpts().OpenCL && RHSVecType && isa<ExtVectorType>(RHSVecType) &&
+ if (getLangOpts().OpenCL &&
+ RHSVecType && isa<ExtVectorType>(RHSVecType) &&
LHSVecType && isa<ExtVectorType>(LHSVecType)) {
- Diag(Loc, diag::err_opencl_implicit_vector_conversion)
- << LHSType << RHSType;
+ Diag(Loc, diag::err_opencl_implicit_vector_conversion) << LHSType
+ << RHSType;
return QualType();
}
+
// If there is a vector type that is not a ExtVector and a scalar, we reach
// this point if scalar could not be converted to the vector's element type
// without truncation.
@@ -11202,15 +11216,17 @@ QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS,
QualType Scalar = LHSVecType ? RHSType : LHSType;
QualType Vector = LHSVecType ? LHSType : RHSType;
unsigned ScalarOrVector = LHSVecType && RHSVecType ? 1 : 0;
- Diag(Loc, diag::err_typecheck_vector_not_convertable_implict_truncation)
+ Diag(Loc,
+ diag::err_typecheck_vector_not_convertable_implict_truncation)
<< ScalarOrVector << Scalar << Vector;
return QualType();
}
// Otherwise, use the generic diagnostic.
- Diag(Loc, DiagID) << LHSType << RHSType << LHS.get()->getSourceRange()
- << RHS.get()->getSourceRange();
+ Diag(Loc, DiagID)
+ << LHSType << RHSType
+ << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
return QualType();
}
@@ -11324,8 +11340,8 @@ static void checkArithmeticNull(Sema &S, ExprResult &LHS, ExprResult &RHS,
return;
S.Diag(Loc, diag::warn_null_in_comparison_operation)
- << LHSNull /* LHS is NULL */ << NonNullType << LHS.get()->getSourceRange()
- << RHS.get()->getSourceRange();
+ << LHSNull /* LHS is NULL */ << NonNullType
+ << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
}
static void DetectPrecisionLossInComplexDivision(Sema &S, QualType DivisorTy,
@@ -11368,7 +11384,7 @@ static void DetectPrecisionLossInComplexDivision(Sema &S, QualType DivisorTy,
}
static void DiagnoseDivisionSizeofPointerOrArray(Sema &S, Expr *LHS, Expr *RHS,
- SourceLocation Loc) {
+ SourceLocation Loc) {
const auto *LUE = dyn_cast<UnaryExprOrTypeTraitExpr>(LHS);
const auto *RUE = dyn_cast<UnaryExprOrTypeTraitExpr>(RHS);
if (!LUE || !RUE)
@@ -11415,7 +11431,7 @@ static void DiagnoseDivisionSizeofPointerOrArray(Sema &S, Expr *LHS, Expr *RHS,
}
}
-static void DiagnoseBadDivideOrRemainderValues(Sema &S, ExprResult &LHS,
+static void DiagnoseBadDivideOrRemainderValues(Sema& S, ExprResult &LHS,
ExprResult &RHS,
SourceLocation Loc, bool IsDiv) {
// Check for division/remainder by zero.
@@ -11425,7 +11441,7 @@ static void DiagnoseBadDivideOrRemainderValues(Sema &S, ExprResult &LHS,
RHSValue.Val.getInt() == 0)
S.DiagRuntimeBehavior(Loc, RHS.get(),
S.PDiag(diag::warn_remainder_division_by_zero)
- << IsDiv << RHS.get()->getSourceRange());
+ << IsDiv << RHS.get()->getSourceRange());
}
static void diagnoseScopedEnums(Sema &S, const SourceLocation Loc,
@@ -11512,8 +11528,8 @@ QualType Sema::CheckMultiplyDivideOperands(ExprResult &LHS, ExprResult &RHS,
return compType;
}
-QualType Sema::CheckRemainderOperands(ExprResult &LHS, ExprResult &RHS,
- SourceLocation Loc, bool IsCompAssign) {
+QualType Sema::CheckRemainderOperands(
+ ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, bool IsCompAssign) {
checkArithmeticNull(*this, LHS, RHS, Loc, /*IsCompare=*/false);
// Note: This check is here to simplify the double exclusions of
@@ -11580,19 +11596,19 @@ QualType Sema::CheckRemainderOperands(ExprResult &LHS, ExprResult &RHS,
static void diagnoseArithmeticOnTwoVoidPointers(Sema &S, SourceLocation Loc,
Expr *LHSExpr, Expr *RHSExpr) {
S.Diag(Loc, S.getLangOpts().CPlusPlus
- ? diag::err_typecheck_pointer_arith_void_type
- : diag::ext_gnu_void_ptr)
- << 1 /* two pointers */ << LHSExpr->getSourceRange()
- << RHSExpr->getSourceRange();
+ ? diag::err_typecheck_pointer_arith_void_type
+ : diag::ext_gnu_void_ptr)
+ << 1 /* two pointers */ << LHSExpr->getSourceRange()
+ << RHSExpr->getSourceRange();
}
/// Diagnose invalid arithmetic on a void pointer.
static void diagnoseArithmeticOnVoidPointer(Sema &S, SourceLocation Loc,
Expr *Pointer) {
S.Diag(Loc, S.getLangOpts().CPlusPlus
- ? diag::err_typecheck_pointer_arith_void_type
- : diag::ext_gnu_void_ptr)
- << 0 /* one pointer */ << Pointer->getSourceRange();
+ ? diag::err_typecheck_pointer_arith_void_type
+ : diag::ext_gnu_void_ptr)
+ << 0 /* one pointer */ << Pointer->getSourceRange();
}
/// Diagnose invalid arithmetic on a null pointer.
@@ -11603,10 +11619,11 @@ static void diagnoseArithmeticOnVoidPointer(Sema &S, SourceLocation Loc,
static void diagnoseArithmeticOnNullPointer(Sema &S, SourceLocation Loc,
Expr *Pointer, bool IsGNUIdiom) {
if (IsGNUIdiom)
- S.Diag(Loc, diag::warn_gnu_null_ptr_arith) << Pointer->getSourceRange();
+ S.Diag(Loc, diag::warn_gnu_null_ptr_arith)
+ << Pointer->getSourceRange();
else
S.Diag(Loc, diag::warn_pointer_arith_null_ptr)
- << S.getLangOpts().CPlusPlus << Pointer->getSourceRange();
+ << S.getLangOpts().CPlusPlus << Pointer->getSourceRange();
}
/// Diagnose invalid subraction on a null pointer.
@@ -11633,15 +11650,14 @@ static void diagnoseArithmeticOnTwoFunctionPointers(Sema &S, SourceLocation Loc,
assert(LHS->getType()->isAnyPointerType());
assert(RHS->getType()->isAnyPointerType());
S.Diag(Loc, S.getLangOpts().CPlusPlus
- ? diag::err_typecheck_pointer_arith_function_type
- : diag::ext_gnu_ptr_func_arith)
- << 1 /* two pointers */
- << LHS->getType()->getPointeeType()
- // We only show the second type if it differs from the first.
- << (unsigned)!S.Context.hasSameUnqualifiedType(LHS->getType(),
- RHS->getType())
- << RHS->getType()->getPointeeType() << LHS->getSourceRange()
- << RHS->getSourceRange();
+ ? diag::err_typecheck_pointer_arith_function_type
+ : diag::ext_gnu_ptr_func_arith)
+ << 1 /* two pointers */ << LHS->getType()->getPointeeType()
+ // We only show the second type if it differs from the first.
+ << (unsigned)!S.Context.hasSameUnqualifiedType(LHS->getType(),
+ RHS->getType())
+ << RHS->getType()->getPointeeType()
+ << LHS->getSourceRange() << RHS->getSourceRange();
}
/// Diagnose invalid arithmetic on a function pointer.
@@ -11649,11 +11665,11 @@ static void diagnoseArithmeticOnFunctionPointer(Sema &S, SourceLocation Loc,
Expr *Pointer) {
assert(Pointer->getType()->isAnyPointerType());
S.Diag(Loc, S.getLangOpts().CPlusPlus
- ? diag::err_typecheck_pointer_arith_function_type
- : diag::ext_gnu_ptr_func_arith)
- << 0 /* one pointer */ << Pointer->getType()->getPointeeType()
- << 0 /* one pointer, so only one type */
- << Pointer->getSourceRange();
+ ? diag::err_typecheck_pointer_arith_function_type
+ : diag::ext_gnu_ptr_func_arith)
+ << 0 /* one pointer */ << Pointer->getType()->getPointeeType()
+ << 0 /* one pointer, so only one type */
+ << Pointer->getSourceRange();
}
/// Emit error if Operand is incomplete pointer type
@@ -11687,8 +11703,7 @@ static bool checkArithmeticOpPointerOperand(Sema &S, SourceLocation Loc,
if (const AtomicType *ResAtomicType = ResType->getAs<AtomicType>())
ResType = ResAtomicType->getValueType();
- if (!ResType->isAnyPointerType())
- return true;
+ if (!ResType->isAnyPointerType()) return true;
QualType PointeeTy = ResType->getPointeeType();
if (PointeeTy->isVoidType()) {
@@ -11700,8 +11715,7 @@ static bool checkArithmeticOpPointerOperand(Sema &S, SourceLocation Loc,
return !S.getLangOpts().CPlusPlus;
}
- if (checkArithmeticIncompletePointerType(S, Loc, Operand))
- return false;
+ if (checkArithmeticIncompletePointerType(S, Loc, Operand)) return false;
return true;
}
@@ -11719,14 +11733,11 @@ static bool checkArithmeticBinOpPointerOperands(Sema &S, SourceLocation Loc,
Expr *LHSExpr, Expr *RHSExpr) {
bool isLHSPointer = LHSExpr->getType()->isAnyPointerType();
bool isRHSPointer = RHSExpr->getType()->isAnyPointerType();
- if (!isLHSPointer && !isRHSPointer)
- return true;
+ if (!isLHSPointer && !isRHSPointer) return true;
QualType LHSPointeeTy, RHSPointeeTy;
- if (isLHSPointer)
- LHSPointeeTy = LHSExpr->getType()->getPointeeType();
- if (isRHSPointer)
- RHSPointeeTy = RHSExpr->getType()->getPointeeType();
+ if (isLHSPointer) LHSPointeeTy = LHSExpr->getType()->getPointeeType();
+ if (isRHSPointer) RHSPointeeTy = RHSExpr->getType()->getPointeeType();
// if both are pointers check if operation is valid wrt address spaces
if (isLHSPointer && isRHSPointer) {
@@ -11744,12 +11755,9 @@ static bool checkArithmeticBinOpPointerOperands(Sema &S, SourceLocation Loc,
bool isLHSVoidPtr = isLHSPointer && LHSPointeeTy->isVoidType();
bool isRHSVoidPtr = isRHSPointer && RHSPointeeTy->isVoidType();
if (isLHSVoidPtr || isRHSVoidPtr) {
- if (!isRHSVoidPtr)
- diagnoseArithmeticOnVoidPointer(S, Loc, LHSExpr);
- else if (!isLHSVoidPtr)
- diagnoseArithmeticOnVoidPointer(S, Loc, RHSExpr);
- else
- diagnoseArithmeticOnTwoVoidPointers(S, Loc, LHSExpr, RHSExpr);
+ if (!isRHSVoidPtr) diagnoseArithmeticOnVoidPointer(S, Loc, LHSExpr);
+ else if (!isLHSVoidPtr) diagnoseArithmeticOnVoidPointer(S, Loc, RHSExpr);
+ else diagnoseArithmeticOnTwoVoidPointers(S, Loc, LHSExpr, RHSExpr);
return !S.getLangOpts().CPlusPlus;
}
@@ -11757,12 +11765,10 @@ static bool checkArithmeticBinOpPointerOperands(Sema &S, SourceLocation Loc,
bool isLHSFuncPtr = isLHSPointer && LHSPointeeTy->isFunctionType();
bool isRHSFuncPtr = isRHSPointer && RHSPointeeTy->isFunctionType();
if (isLHSFuncPtr || isRHSFuncPtr) {
- if (!isRHSFuncPtr)
- diagnoseArithmeticOnFunctionPointer(S, Loc, LHSExpr);
- else if (!isLHSFuncPtr)
- diagnoseArithmeticOnFunctionPointer(S, Loc, RHSExpr);
- else
- diagnoseArithmeticOnTwoFunctionPointers(S, Loc, LHSExpr, RHSExpr);
+ if (!isRHSFuncPtr) diagnoseArithmeticOnFunctionPointer(S, Loc, LHSExpr);
+ else if (!isLHSFuncPtr) diagnoseArithmeticOnFunctionPointer(S, Loc,
+ RHSExpr);
+ else diagnoseArithmeticOnTwoFunctionPointers(S, Loc, LHSExpr, RHSExpr);
return !S.getLangOpts().CPlusPlus;
}
@@ -11779,15 +11785,15 @@ static bool checkArithmeticBinOpPointerOperands(Sema &S, SourceLocation Loc,
/// literal.
static void diagnoseStringPlusInt(Sema &Self, SourceLocation OpLoc,
Expr *LHSExpr, Expr *RHSExpr) {
- StringLiteral *StrExpr = dyn_cast<StringLiteral>(LHSExpr->IgnoreImpCasts());
- Expr *IndexExpr = RHSExpr;
+ StringLiteral* StrExpr = dyn_cast<StringLiteral>(LHSExpr->IgnoreImpCasts());
+ Expr* IndexExpr = RHSExpr;
if (!StrExpr) {
StrExpr = dyn_cast<StringLiteral>(RHSExpr->IgnoreImpCasts());
IndexExpr = LHSExpr;
}
- bool IsStringPlusInt =
- StrExpr && IndexExpr->getType()->isIntegralOrUnscopedEnumerationType();
+ bool IsStringPlusInt = StrExpr &&
+ IndexExpr->getType()->isIntegralOrUnscopedEnumerationType();
if (!IsStringPlusInt || IndexExpr->isValueDependent())
return;
@@ -11835,9 +11841,11 @@ static void diagnoseStringPlusChar(Sema &Self, SourceLocation OpLoc,
SourceRange DiagRange(LHSExpr->getBeginLoc(), RHSExpr->getEndLoc());
const QualType CharType = CharExpr->getType();
- if (!CharType->isAnyCharacterType() && CharType->isIntegerType() &&
+ if (!CharType->isAnyCharacterType() &&
+ CharType->isIntegerType() &&
llvm::isUIntN(Ctx.getCharWidth(), CharExpr->getValue())) {
- Self.Diag(OpLoc, diag::warn_string_plus_char) << DiagRange << Ctx.CharTy;
+ Self.Diag(OpLoc, diag::warn_string_plus_char)
+ << DiagRange << Ctx.CharTy;
} else {
Self.Diag(OpLoc, diag::warn_string_plus_char)
<< DiagRange << CharExpr->getType();
@@ -11861,14 +11869,14 @@ static void diagnosePointerIncompatibility(Sema &S, SourceLocation Loc,
assert(LHSExpr->getType()->isAnyPointerType());
assert(RHSExpr->getType()->isAnyPointerType());
S.Diag(Loc, diag::err_typecheck_sub_ptr_compatible)
- << LHSExpr->getType() << RHSExpr->getType() << LHSExpr->getSourceRange()
- << RHSExpr->getSourceRange();
+ << LHSExpr->getType() << RHSExpr->getType() << LHSExpr->getSourceRange()
+ << RHSExpr->getSourceRange();
}
// C99 6.5.6
QualType Sema::CheckAdditionOperands(ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc, BinaryOperatorKind Opc,
- QualType *CompLHSTy) {
+ QualType* CompLHSTy) {
checkArithmeticNull(*this, LHS, RHS, Loc, /*IsCompare=*/false);
if (LHS.get()->getType()->isVectorType() ||
@@ -11879,8 +11887,7 @@ QualType Sema::CheckAdditionOperands(ExprResult &LHS, ExprResult &RHS,
/*AllowBoolConversions*/ getLangOpts().ZVector,
/*AllowBooleanOperation*/ false,
/*ReportInvalid*/ true);
- if (CompLHSTy)
- *CompLHSTy = compType;
+ if (CompLHSTy) *CompLHSTy = compType;
return compType;
}
@@ -11916,8 +11923,7 @@ QualType Sema::CheckAdditionOperands(ExprResult &LHS, ExprResult &RHS,
// handle the common case first (both operands are arithmetic).
if (!compType.isNull() && compType->isArithmeticType()) {
- if (CompLHSTy)
- *CompLHSTy = compType;
+ if (CompLHSTy) *CompLHSTy = compType;
return compType;
}
@@ -11952,9 +11958,10 @@ QualType Sema::CheckAdditionOperands(ExprResult &LHS, ExprResult &RHS,
Context, Expr::NPC_ValueDependentIsNotNull)) {
// In C++ adding zero to a null pointer is defined.
Expr::EvalResult KnownVal;
- if (!getLangOpts().CPlusPlus || (!IExp->isValueDependent() &&
- (!IExp->EvaluateAsInt(KnownVal, Context) ||
- KnownVal.Val.getInt() != 0))) {
+ if (!getLangOpts().CPlusPlus ||
+ (!IExp->isValueDependent() &&
+ (!IExp->EvaluateAsInt(KnownVal, Context) ||
+ KnownVal.Val.getInt() != 0))) {
// Check the conditions to see if this is the 'p = nullptr + n' idiom.
bool IsGNUIdiom = BinaryOperator::isNullPointerArithmeticExtension(
Context, BO_Add, PExp, IExp);
@@ -12027,8 +12034,7 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS,
/*AllowBoolConversions*/ getLangOpts().ZVector,
/*AllowBooleanOperation*/ false,
/*ReportInvalid*/ true);
- if (CompLHSTy)
- *CompLHSTy = compType;
+ if (CompLHSTy) *CompLHSTy = compType;
return compType;
}
@@ -12060,8 +12066,7 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS,
// Handle the common case first (both operands are arithmetic).
if (!compType.isNull() && compType->isArithmeticType()) {
- if (CompLHSTy)
- *CompLHSTy = compType;
+ if (CompLHSTy) *CompLHSTy = compType;
return compType;
}
@@ -12088,8 +12093,8 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS,
// Subtracting from a null pointer should produce a warning.
// The last argument to the diagnose call says this doesn't match the
// GNU int-to-pointer idiom.
- if (LHS.get()->IgnoreParenCasts()->isNullPointerConstant(
- Context, Expr::NPC_ValueDependentIsNotNull)) {
+ if (LHS.get()->IgnoreParenCasts()->isNullPointerConstant(Context,
+ Expr::NPC_ValueDependentIsNotNull)) {
// In C++ adding zero to a null pointer is defined.
Expr::EvalResult KnownVal;
if (!getLangOpts().CPlusPlus ||
@@ -12104,17 +12109,16 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS,
return QualType();
// Check array bounds for pointer arithemtic
- CheckArrayAccess(LHS.get(), RHS.get(), /*ArraySubscriptExpr*/ nullptr,
- /*AllowOnePastEnd*/ true, /*IndexNegated*/ true);
+ CheckArrayAccess(LHS.get(), RHS.get(), /*ArraySubscriptExpr*/nullptr,
+ /*AllowOnePastEnd*/true, /*IndexNegated*/true);
- if (CompLHSTy)
- *CompLHSTy = LHS.get()->getType();
+ if (CompLHSTy) *CompLHSTy = LHS.get()->getType();
return LHS.get()->getType();
}
// Handle pointer-pointer subtractions.
- if (const PointerType *RHSPTy =
- RHS.get()->getType()->getAs<PointerType>()) {
+ if (const PointerType *RHSPTy
+ = RHS.get()->getType()->getAs<PointerType>()) {
QualType rpointee = RHSPTy->getPointeeType();
if (getLangOpts().CPlusPlus) {
@@ -12132,8 +12136,8 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS,
}
}
- if (!checkArithmeticBinOpPointerOperands(*this, Loc, LHS.get(),
- RHS.get()))
+ if (!checkArithmeticBinOpPointerOperands(*this, Loc,
+ LHS.get(), RHS.get()))
return QualType();
// For pointer subtraction, if the address spaces differ but overlap,
@@ -12186,8 +12190,7 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS,
<< rpointee.getUnqualifiedType() << LHS.get()->getSourceRange()
<< RHS.get()->getSourceRange();
- if (CompLHSTy)
- *CompLHSTy = LHS.get()->getType();
+ if (CompLHSTy) *CompLHSTy = LHS.get()->getType();
return Context.getPointerDiffType();
}
}
@@ -12203,12 +12206,11 @@ static bool isScopedEnumerationType(QualType T) {
return false;
}
-static void DiagnoseBadShiftValues(Sema &S, ExprResult &LHS, ExprResult &RHS,
+static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc, BinaryOperatorKind Opc,
QualType LHSType) {
- // OpenCL 6.3j: shift values are effectively % word size of LHS (more
- // defined), so skip remaining warnings as we don't want to modify values
- // within Sema.
+ // OpenCL 6.3j: shift values are effectively % word size of LHS (more defined),
+ // so skip remaining warnings as we don't want to modify values within Sema.
if (S.getLangOpts().OpenCL)
return;
@@ -12296,8 +12298,8 @@ static void DiagnoseBadShiftValues(Sema &S, ExprResult &LHS, ExprResult &RHS,
// turned off separately if needed.
if (ResultBits - 1 == LeftSize) {
S.Diag(Loc, diag::warn_shift_result_sets_sign_bit)
- << HexResult << LHSType << LHS.get()->getSourceRange()
- << RHS.get()->getSourceRange();
+ << HexResult << LHSType
+ << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
return;
}
@@ -12315,20 +12317,18 @@ static QualType checkVectorShift(Sema &S, ExprResult &LHS, ExprResult &RHS,
if ((S.LangOpts.OpenCL || S.LangOpts.ZVector) &&
!LHS.get()->getType()->isVectorType()) {
S.Diag(Loc, diag::err_shift_rhs_only_vector)
- << RHS.get()->getType() << LHS.get()->getType()
- << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+ << RHS.get()->getType() << LHS.get()->getType()
+ << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
return QualType();
}
if (!IsCompAssign) {
LHS = S.UsualUnaryConversions(LHS.get());
- if (LHS.isInvalid())
- return QualType();
+ if (LHS.isInvalid()) return QualType();
}
RHS = S.UsualUnaryConversions(RHS.get());
- if (RHS.isInvalid())
- return QualType();
+ if (RHS.isInvalid()) return QualType();
QualType LHSType = LHS.get()->getType();
// Note that LHS might be a scalar because the routine calls not only in
@@ -12353,13 +12353,13 @@ static QualType checkVectorShift(Sema &S, ExprResult &LHS, ExprResult &RHS,
// The operands need to be integers.
if (!LHSEleType->isIntegerType()) {
S.Diag(Loc, diag::err_typecheck_expect_int)
- << LHS.get()->getType() << LHS.get()->getSourceRange();
+ << LHS.get()->getType() << LHS.get()->getSourceRange();
return QualType();
}
if (!RHSEleType->isIntegerType()) {
S.Diag(Loc, diag::err_typecheck_expect_int)
- << RHS.get()->getType() << RHS.get()->getSourceRange();
+ << RHS.get()->getType() << RHS.get()->getSourceRange();
return QualType();
}
@@ -12368,7 +12368,7 @@ static QualType checkVectorShift(Sema &S, ExprResult &LHS, ExprResult &RHS,
if (IsCompAssign)
return RHSType;
if (LHSEleType != RHSEleType) {
- LHS = S.ImpCastExprToType(LHS.get(), RHSEleType, CK_IntegralCast);
+ LHS = S.ImpCastExprToType(LHS.get(),RHSEleType, CK_IntegralCast);
LHSEleType = RHSEleType;
}
QualType VecTy =
@@ -12381,8 +12381,8 @@ static QualType checkVectorShift(Sema &S, ExprResult &LHS, ExprResult &RHS,
// that the number of elements is the same as LHS...
if (RHSVecTy->getNumElements() != LHSVecTy->getNumElements()) {
S.Diag(Loc, diag::err_typecheck_vector_lengths_not_equal)
- << LHS.get()->getType() << RHS.get()->getType()
- << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+ << LHS.get()->getType() << RHS.get()->getType()
+ << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
return QualType();
}
if (!S.LangOpts.OpenCL && !S.LangOpts.ZVector) {
@@ -12398,7 +12398,7 @@ static QualType checkVectorShift(Sema &S, ExprResult &LHS, ExprResult &RHS,
} else {
// ...else expand RHS to match the number of elements in LHS.
QualType VecTy =
- S.Context.getExtVectorType(RHSEleType, LHSVecTy->getNumElements());
+ S.Context.getExtVectorType(RHSEleType, LHSVecTy->getNumElements());
RHS = S.ImpCastExprToType(RHS.get(), VecTy, CK_VectorSplat);
}
@@ -12533,8 +12533,7 @@ QualType Sema::CheckShiftOperands(ExprResult &LHS, ExprResult &RHS,
if (LHS.isInvalid())
return QualType();
QualType LHSType = LHS.get()->getType();
- if (IsCompAssign)
- LHS = OldLHS;
+ if (IsCompAssign) LHS = OldLHS;
// The RHS is simpler.
RHS = UsualUnaryConversions(RHS.get());
@@ -12564,8 +12563,8 @@ static void diagnoseDistinctPointerComparison(Sema &S, SourceLocation Loc,
bool IsError) {
S.Diag(Loc, IsError ? diag::err_typecheck_comparison_of_distinct_pointers
: diag::ext_typecheck_comparison_of_distinct_pointers)
- << LHS.get()->getType() << RHS.get()->getType()
- << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+ << LHS.get()->getType() << RHS.get()->getType()
+ << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
}
/// Returns false if the pointers are converted to a composite type,
@@ -12590,7 +12589,7 @@ static bool convertPointersToCompositeType(Sema &S, SourceLocation Loc,
if (T.isNull()) {
if ((LHSType->isAnyPointerType() || LHSType->isMemberPointerType()) &&
(RHSType->isAnyPointerType() || RHSType->isMemberPointerType()))
- diagnoseDistinctPointerComparison(S, Loc, LHS, RHS, /*isError*/ true);
+ diagnoseDistinctPointerComparison(S, Loc, LHS, RHS, /*isError*/true);
else
S.InvalidOperands(Loc, LHS, RHS);
return true;
@@ -12605,8 +12604,8 @@ static void diagnoseFunctionPointerToVoidComparison(Sema &S, SourceLocation Loc,
bool IsError) {
S.Diag(Loc, IsError ? diag::err_typecheck_comparison_of_fptr_to_void
: diag::ext_typecheck_comparison_of_fptr_to_void)
- << LHS.get()->getType() << RHS.get()->getType()
- << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+ << LHS.get()->getType() << RHS.get()->getType()
+ << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
}
static bool isObjCObjectLiteral(ExprResult &E) {
@@ -12624,7 +12623,7 @@ static bool isObjCObjectLiteral(ExprResult &E) {
static bool hasIsEqualMethod(Sema &S, const Expr *LHS, const Expr *RHS) {
const ObjCObjectPointerType *Type =
- LHS->getType()->getAs<ObjCObjectPointerType>();
+ LHS->getType()->getAs<ObjCObjectPointerType>();
// If this is not actually an Objective-C object, bail out.
if (!Type)
@@ -12671,7 +12670,7 @@ static bool hasIsEqualMethod(Sema &S, const Expr *LHS, const Expr *RHS) {
static void diagnoseObjCLiteralComparison(Sema &S, SourceLocation Loc,
ExprResult &LHS, ExprResult &RHS,
- BinaryOperator::Opcode Opc) {
+ BinaryOperator::Opcode Opc){
Expr *Literal;
Expr *Other;
if (isObjCObjectLiteral(LHS)) {
@@ -12699,22 +12698,22 @@ static void diagnoseObjCLiteralComparison(Sema &S, SourceLocation Loc,
if (LiteralKind == SemaObjC::LK_String)
S.Diag(Loc, diag::warn_objc_string_literal_comparison)
- << Literal->getSourceRange();
+ << Literal->getSourceRange();
else
S.Diag(Loc, diag::warn_objc_literal_comparison)
- << LiteralKind << Literal->getSourceRange();
+ << LiteralKind << Literal->getSourceRange();
if (BinaryOperator::isEqualityOp(Opc) &&
hasIsEqualMethod(S, LHS.get(), RHS.get())) {
SourceLocation Start = LHS.get()->getBeginLoc();
SourceLocation End = S.getLocForEndOfToken(RHS.get()->getEndLoc());
CharSourceRange OpRange =
- CharSourceRange::getCharRange(Loc, S.getLocForEndOfToken(Loc));
+ CharSourceRange::getCharRange(Loc, S.getLocForEndOfToken(Loc));
S.Diag(Loc, diag::note_objc_literal_comparison_isequal)
- << FixItHint::CreateInsertion(Start, Opc == BO_EQ ? "[" : "![")
- << FixItHint::CreateReplacement(OpRange, " isEqual:")
- << FixItHint::CreateInsertion(End, "]");
+ << FixItHint::CreateInsertion(Start, Opc == BO_EQ ? "[" : "![")
+ << FixItHint::CreateReplacement(OpRange, " isEqual:")
+ << FixItHint::CreateInsertion(End, "]");
}
}
@@ -12724,17 +12723,14 @@ static void diagnoseLogicalNotOnLHSofCheck(Sema &S, ExprResult &LHS,
BinaryOperatorKind Opc) {
// Check that left hand side is !something.
UnaryOperator *UO = dyn_cast<UnaryOperator>(LHS.get()->IgnoreImpCasts());
- if (!UO || UO->getOpcode() != UO_LNot)
- return;
+ if (!UO || UO->getOpcode() != UO_LNot) return;
// Only check if the right hand side is non-bool arithmetic type.
- if (RHS.get()->isKnownToHaveBooleanValue())
- return;
+ if (RHS.get()->isKnownToHaveBooleanValue()) return;
// Make sure that the something in !something is not bool.
Expr *SubExpr = UO->getSubExpr()->IgnoreImpCasts();
- if (SubExpr->isKnownToHaveBooleanValue())
- return;
+ if (SubExpr->isKnownToHaveBooleanValue()) return;
// Emit warning.
bool IsBitwiseOp = Opc == BO_And || Opc == BO_Or || Opc == BO_Xor;
@@ -12748,7 +12744,8 @@ static void diagnoseLogicalNotOnLHSofCheck(Sema &S, ExprResult &LHS,
if (FirstClose.isInvalid())
FirstOpen = SourceLocation();
S.Diag(UO->getOperatorLoc(), diag::note_logical_not_fix)
- << IsBitwiseOp << FixItHint::CreateInsertion(FirstOpen, "(")
+ << IsBitwiseOp
+ << FixItHint::CreateInsertion(FirstOpen, "(")
<< FixItHint::CreateInsertion(FirstClose, ")");
// Second note suggests (!x) < y
@@ -12955,8 +12952,8 @@ static void diagnoseTautologicalComparison(Sema &S, SourceLocation Loc,
LiteralStringStripped = LHSStripped;
} else if ((isa<StringLiteral>(RHSStripped) ||
isa<ObjCEncodeExpr>(RHSStripped)) &&
- !LHSStripped->isNullPointerConstant(
- S.Context, Expr::NPC_ValueDependentIsNull)) {
+ !LHSStripped->isNullPointerConstant(S.Context,
+ Expr::NPC_ValueDependentIsNull)) {
LiteralString = RHS;
LiteralStringStripped = RHSStripped;
}
@@ -13172,7 +13169,7 @@ void Sema::CheckPtrComparisonWithNullChar(ExprResult &E, ExprResult &NullE) {
if (!E.get()->getType()->isAnyPointerType() &&
E.get()->isNullPointerConstant(Context,
Expr::NPC_ValueDependentIsNotNull) ==
- Expr::NPCK_ZeroExpression) {
+ Expr::NPCK_ZeroExpression) {
if (const auto *CL = dyn_cast<CharacterLiteral>(E.get())) {
if (CL->getValue() == 0)
Diag(E.get()->getExprLoc(), diag::warn_pointer_compare)
@@ -13180,14 +13177,14 @@ void Sema::CheckPtrComparisonWithNullChar(ExprResult &E, ExprResult &NullE) {
<< FixItHint::CreateReplacement(E.get()->getExprLoc(),
NullValue ? "NULL" : "(void *)0");
} else if (const auto *CE = dyn_cast<CStyleCastExpr>(E.get())) {
- TypeSourceInfo *TI = CE->getTypeInfoAsWritten();
- QualType T = Context.getCanonicalType(TI->getType()).getUnqualifiedType();
- if (T == Context.CharTy)
- Diag(E.get()->getExprLoc(), diag::warn_pointer_compare)
- << NullValue
- << FixItHint::CreateReplacement(E.get()->getExprLoc(),
- NullValue ? "NULL" : "(void *)0");
- }
+ TypeSourceInfo *TI = CE->getTypeInfoAsWritten();
+ QualType T = Context.getCanonicalType(TI->getType()).getUnqualifiedType();
+ if (T == Context.CharTy)
+ Diag(E.get()->getExprLoc(), diag::warn_pointer_compare)
+ << NullValue
+ << FixItHint::CreateReplacement(E.get()->getExprLoc(),
+ NullValue ? "NULL" : "(void *)0");
+ }
}
}
@@ -13368,9 +13365,9 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
// All of the following pointer-related warnings are GCC extensions, except
// when handling null pointer constants.
QualType LCanPointeeTy =
- LHSType->castAs<PointerType>()->getPointeeType().getCanonicalType();
+ LHSType->castAs<PointerType>()->getPointeeType().getCanonicalType();
QualType RCanPointeeTy =
- RHSType->castAs<PointerType>()->getPointeeType().getCanonicalType();
+ RHSType->castAs<PointerType>()->getPointeeType().getCanonicalType();
// C99 6.5.9p2 and C99 6.5.8p2
if (Context.typesAreCompatible(LCanPointeeTy.getUnqualifiedType(),
@@ -13389,15 +13386,13 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
} else if (!IsRelational &&
(LCanPointeeTy->isVoidType() || RCanPointeeTy->isVoidType())) {
// Valid unless comparison between non-null pointer and function pointer
- if ((LCanPointeeTy->isFunctionType() ||
- RCanPointeeTy->isFunctionType()) &&
- !LHSIsNull && !RHSIsNull)
+ if ((LCanPointeeTy->isFunctionType() || RCanPointeeTy->isFunctionType())
+ && !LHSIsNull && !RHSIsNull)
diagnoseFunctionPointerToVoidComparison(*this, Loc, LHS, RHS,
- /*isError*/ false);
+ /*isError*/false);
} else {
// Invalid
- diagnoseDistinctPointerComparison(*this, Loc, LHS, RHS,
- /*isError*/ false);
+ diagnoseDistinctPointerComparison(*this, Loc, LHS, RHS, /*isError*/false);
}
if (LCanPointeeTy != RCanPointeeTy) {
// Treat NULL constant as a special case in OpenCL.
@@ -13412,8 +13407,8 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
}
LangAS AddrSpaceL = LCanPointeeTy.getAddressSpace();
LangAS AddrSpaceR = RCanPointeeTy.getAddressSpace();
- CastKind Kind =
- AddrSpaceL != AddrSpaceR ? CK_AddressSpaceConversion : CK_BitCast;
+ CastKind Kind = AddrSpaceL != AddrSpaceR ? CK_AddressSpaceConversion
+ : CK_BitCast;
const FunctionType *LFn = LCanPointeeTy->getAs<FunctionType>();
const FunctionType *RFn = RCanPointeeTy->getAs<FunctionType>();
@@ -13430,6 +13425,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
return computeResultTy();
}
+
// C++ [expr.eq]p4:
// Two operands of type std::nullptr_t or one operand of type
// std::nullptr_t and the other a null pointer constant compare
@@ -13524,36 +13520,34 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
if (!LHSIsNull && !RHSIsNull &&
!Context.typesAreCompatible(lpointee, rpointee)) {
Diag(Loc, diag::err_typecheck_comparison_of_distinct_blocks)
- << LHSType << RHSType << LHS.get()->getSourceRange()
- << RHS.get()->getSourceRange();
+ << LHSType << RHSType << LHS.get()->getSourceRange()
+ << RHS.get()->getSourceRange();
}
RHS = ImpCastExprToType(RHS.get(), LHSType, CK_BitCast);
return computeResultTy();
}
// Allow block pointers to be compared with null pointer constants.
- if (!IsOrdered &&
- ((LHSType->isBlockPointerType() && RHSType->isPointerType()) ||
- (LHSType->isPointerType() && RHSType->isBlockPointerType()))) {
+ if (!IsOrdered
+ && ((LHSType->isBlockPointerType() && RHSType->isPointerType())
+ || (LHSType->isPointerType() && RHSType->isBlockPointerType()))) {
if (!LHSIsNull && !RHSIsNull) {
- if (!((RHSType->isPointerType() &&
- RHSType->castAs<PointerType>()->getPointeeType()->isVoidType()) ||
- (LHSType->isPointerType() &&
- LHSType->castAs<PointerType>()->getPointeeType()->isVoidType())))
+ if (!((RHSType->isPointerType() && RHSType->castAs<PointerType>()
+ ->getPointeeType()->isVoidType())
+ || (LHSType->isPointerType() && LHSType->castAs<PointerType>()
+ ->getPointeeType()->isVoidType())))
Diag(Loc, diag::err_typecheck_comparison_of_distinct_blocks)
- << LHSType << RHSType << LHS.get()->getSourceRange()
- << RHS.get()->getSourceRange();
+ << LHSType << RHSType << LHS.get()->getSourceRange()
+ << RHS.get()->getSourceRange();
}
if (LHSIsNull && !RHSIsNull)
LHS = ImpCastExprToType(LHS.get(), RHSType,
- RHSType->isPointerType()
- ? CK_BitCast
- : CK_AnyPointerToBlockPointerCast);
+ RHSType->isPointerType() ? CK_BitCast
+ : CK_AnyPointerToBlockPointerCast);
else
RHS = ImpCastExprToType(RHS.get(), LHSType,
- LHSType->isPointerType()
- ? CK_BitCast
- : CK_AnyPointerToBlockPointerCast);
+ LHSType->isPointerType() ? CK_BitCast
+ : CK_AnyPointerToBlockPointerCast);
return computeResultTy();
}
@@ -13568,7 +13562,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
if (!LPtrToVoid && !RPtrToVoid &&
!Context.typesAreCompatible(LHSType, RHSType)) {
diagnoseDistinctPointerComparison(*this, Loc, LHS, RHS,
- /*isError*/ false);
+ /*isError*/false);
}
// FIXME: If LPtrToVoid, we should presumably convert the LHS rather than
// the RHS, but we have test coverage for this behavior.
@@ -13578,17 +13572,18 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
if (getLangOpts().ObjCAutoRefCount)
ObjC().CheckObjCConversion(SourceRange(), RHSType, E,
CheckedConversionKind::Implicit);
- LHS = ImpCastExprToType(
- E, RHSType, RPT ? CK_BitCast : CK_CPointerToObjCPointerCast);
- } else {
+ LHS = ImpCastExprToType(E, RHSType,
+ RPT ? CK_BitCast :CK_CPointerToObjCPointerCast);
+ }
+ else {
Expr *E = RHS.get();
if (getLangOpts().ObjCAutoRefCount)
ObjC().CheckObjCConversion(SourceRange(), LHSType, E,
CheckedConversionKind::Implicit,
/*Diagnose=*/true,
/*DiagnoseCFAudited=*/false, Opc);
- RHS = ImpCastExprToType(
- E, LHSType, LPT ? CK_BitCast : CK_CPointerToObjCPointerCast);
+ RHS = ImpCastExprToType(E, LHSType,
+ LPT ? CK_BitCast :CK_CPointerToObjCPointerCast);
}
return computeResultTy();
}
@@ -13596,7 +13591,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
RHSType->isObjCObjectPointerType()) {
if (!Context.areComparableObjCPointerTypes(LHSType, RHSType))
diagnoseDistinctPointerComparison(*this, Loc, LHS, RHS,
- /*isError*/ false);
+ /*isError*/false);
if (isObjCObjectLiteral(LHS) || isObjCObjectLiteral(RHS))
diagnoseObjCLiteralComparison(*this, Loc, LHS, RHS, Opc);
@@ -13632,9 +13627,8 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
if (IsOrdered) {
isError = getLangOpts().CPlusPlus;
DiagID =
- isError
- ? diag::err_typecheck_ordered_comparison_of_pointer_and_zero
- : diag::ext_typecheck_ordered_comparison_of_pointer_and_zero;
+ isError ? diag::err_typecheck_ordered_comparison_of_pointer_and_zero
+ : diag::ext_typecheck_ordered_comparison_of_pointer_and_zero;
}
} else if (getLangOpts().CPlusPlus) {
DiagID = diag::err_typecheck_comparison_of_pointer_integer;
@@ -13645,31 +13639,30 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
DiagID = diag::ext_typecheck_comparison_of_pointer_integer;
if (DiagID) {
- Diag(Loc, DiagID) << LHSType << RHSType << LHS.get()->getSourceRange()
- << RHS.get()->getSourceRange();
+ Diag(Loc, DiagID)
+ << LHSType << RHSType << LHS.get()->getSourceRange()
+ << RHS.get()->getSourceRange();
if (isError)
return QualType();
}
if (LHSType->isIntegerType())
LHS = ImpCastExprToType(LHS.get(), RHSType,
- LHSIsNull ? CK_NullToPointer
- : CK_IntegralToPointer);
+ LHSIsNull ? CK_NullToPointer : CK_IntegralToPointer);
else
RHS = ImpCastExprToType(RHS.get(), LHSType,
- RHSIsNull ? CK_NullToPointer
- : CK_IntegralToPointer);
+ RHSIsNull ? CK_NullToPointer : CK_IntegralToPointer);
return computeResultTy();
}
// Handle block pointers.
- if (!IsOrdered && RHSIsNull && LHSType->isBlockPointerType() &&
- RHSType->isIntegerType()) {
+ if (!IsOrdered && RHSIsNull
+ && LHSType->isBlockPointerType() && RHSType->isIntegerType()) {
RHS = ImpCastExprToType(RHS.get(), LHSType, CK_NullToPointer);
return computeResultTy();
}
- if (!IsOrdered && LHSIsNull && LHSType->isIntegerType() &&
- RHSType->isBlockPointerType()) {
+ if (!IsOrdered && LHSIsNull
+ && LHSType->isIntegerType() && RHSType->isBlockPointerType()) {
LHS = ImpCastExprToType(LHS.get(), RHSType, CK_NullToPointer);
return computeResultTy();
}
@@ -14353,14 +14346,11 @@ inline QualType Sema::CheckLogicalOperands(ExprResult &LHS, ExprResult &RHS,
static bool IsReadonlyMessage(Expr *E, Sema &S) {
const MemberExpr *ME = dyn_cast<MemberExpr>(E);
- if (!ME)
- return false;
- if (!isa<FieldDecl>(ME->getMemberDecl()))
- return false;
+ if (!ME) return false;
+ if (!isa<FieldDecl>(ME->getMemberDecl())) return false;
ObjCMessageExpr *Base = dyn_cast<ObjCMessageExpr>(
ME->getBase()->IgnoreImplicit()->IgnoreParenImpCasts());
- if (!Base)
- return false;
+ if (!Base) return false;
return Base->getMethodDecl() != nullptr;
}
@@ -14374,10 +14364,8 @@ static NonConstCaptureKind isReferenceToNonConstCapture(Sema &S, Expr *E) {
// Must be a reference to a declaration from an enclosing scope.
DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E);
- if (!DRE)
- return NCCK_None;
- if (!DRE->refersToEnclosingVariableOrCapture())
- return NCCK_None;
+ if (!DRE) return NCCK_None;
+ if (!DRE->refersToEnclosingVariableOrCapture()) return NCCK_None;
ValueDecl *Value = DRE->getDecl();
@@ -14516,8 +14504,8 @@ static void DiagnoseConstAssignment(Sema &S, const Expr *E,
const FunctionDecl *FD = CE->getDirectCallee();
if (FD && !IsTypeModifiable(FD->getReturnType(), IsDereference)) {
if (!DiagnosticEmitted) {
- S.Diag(Loc, diag::err_typecheck_assign_const)
- << ExprRange << ConstFunction << FD;
+ S.Diag(Loc, diag::err_typecheck_assign_const) << ExprRange
+ << ConstFunction << FD;
DiagnosticEmitted = true;
}
S.Diag(FD->getReturnTypeSourceRange().getBegin(),
@@ -14561,7 +14549,11 @@ static void DiagnoseConstAssignment(Sema &S, const Expr *E,
S.Diag(Loc, diag::err_typecheck_assign_const) << ExprRange << ConstUnknown;
}
-enum OriginalExprKind { OEK_Variable, OEK_Member, OEK_LValue };
+enum OriginalExprKind {
+ OEK_Variable,
+ OEK_Member,
+ OEK_LValue
+};
static void DiagnoseRecursiveConstFields(Sema &S, const ValueDecl *VD,
const RecordType *Ty,
@@ -14584,12 +14576,13 @@ static void DiagnoseRecursiveConstFields(Sema &S, const ValueDecl *VD,
if (FieldTy.isConstQualified()) {
if (!DiagnosticEmitted) {
S.Diag(Loc, diag::err_typecheck_assign_const)
- << Range << NestedConstMember << OEK << VD << IsNested << Field;
+ << Range << NestedConstMember << OEK << VD
+ << IsNested << Field;
DiagnosticEmitted = true;
}
S.Diag(Field->getLocation(), diag::note_typecheck_assign_const)
- << NestedConstMember << IsNested << Field << FieldTy
- << Field->getSourceRange();
+ << NestedConstMember << IsNested << Field
+ << FieldTy << Field->getSourceRange();
}
// Then we append it to the list to check next in order.
@@ -14614,14 +14607,14 @@ static void DiagnoseRecursiveConstFields(Sema &S, const Expr *E,
bool DiagEmitted = false;
if (const MemberExpr *ME = dyn_cast<MemberExpr>(E))
- DiagnoseRecursiveConstFields(S, ME->getMemberDecl(), RTy, Loc, Range,
- OEK_Member, DiagEmitted);
+ DiagnoseRecursiveConstFields(S, ME->getMemberDecl(), RTy, Loc,
+ Range, OEK_Member, DiagEmitted);
else if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
- DiagnoseRecursiveConstFields(S, DRE->getDecl(), RTy, Loc, Range,
- OEK_Variable, DiagEmitted);
+ DiagnoseRecursiveConstFields(S, DRE->getDecl(), RTy, Loc,
+ Range, OEK_Variable, DiagEmitted);
else
- DiagnoseRecursiveConstFields(S, nullptr, RTy, Loc, Range, OEK_LValue,
- DiagEmitted);
+ DiagnoseRecursiveConstFields(S, nullptr, RTy, Loc,
+ Range, OEK_LValue, DiagEmitted);
if (!DiagEmitted)
DiagnoseConstAssignment(S, E, Loc);
}
@@ -14634,7 +14627,8 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
S.CheckShadowingDeclModification(E, Loc);
SourceLocation OrigLoc = Loc;
- Expr::isModifiableLvalueResult IsLV = E->isModifiableLvalue(S.Context, &Loc);
+ Expr::isModifiableLvalueResult IsLV = E->isModifiableLvalue(S.Context,
+ &Loc);
if (IsLV == Expr::MLV_ClassTemporary && IsReadonlyMessage(E, S))
IsLV = Expr::MLV_InvalidMessageExpression;
if (IsLV == Expr::MLV_Valid)
@@ -14671,15 +14665,15 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
ObjCMethodDecl *method = S.getCurMethodDecl();
if (method && var == method->getSelfDecl()) {
DiagID = method->isClassMethod()
- ? diag::err_typecheck_arc_assign_self_class_method
- : diag::err_typecheck_arc_assign_self;
+ ? diag::err_typecheck_arc_assign_self_class_method
+ : diag::err_typecheck_arc_assign_self;
- // - Objective-C externally_retained attribute.
+ // - Objective-C externally_retained attribute.
} else if (var->hasAttr<ObjCExternallyRetainedAttr>() ||
isa<ParmVarDecl>(var)) {
DiagID = diag::err_typecheck_arc_assign_externally_retained;
- // - fast enumeration variables
+ // - fast enumeration variables
} else {
DiagID = diag::err_typecheck_arr_assign_enumeration;
}
@@ -14730,9 +14724,8 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
break;
case Expr::MLV_IncompleteType:
case Expr::MLV_IncompleteVoidType:
- return S.RequireCompleteType(
- Loc, E->getType(),
- diag::err_typecheck_incomplete_type_not_modifiable_lvalue, E);
+ return S.RequireCompleteType(Loc, E->getType(),
+ diag::err_typecheck_incomplete_type_not_modifiable_lvalue, E);
case Expr::MLV_DuplicateVectorComponents:
DiagID = diag::err_typecheck_duplicate_vector_components_not_mlvalue;
break;
@@ -14760,7 +14753,8 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
}
static void CheckIdentityFieldAssignment(Expr *LHSExpr, Expr *RHSExpr,
- SourceLocation Loc, Sema &Sema) {
+ SourceLocation Loc,
+ Sema &Sema) {
if (Sema.inTemplateInstantiation())
return;
if (Sema.isUnevaluatedContext())
@@ -14814,8 +14808,8 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS,
return QualType();
QualType LHSType = LHSExpr->getType();
- QualType RHSType =
- CompoundType.isNull() ? RHS.get()->getType() : CompoundType;
+ QualType RHSType = CompoundType.isNull() ? RHS.get()->getType() :
+ CompoundType;
if (RHS.isUsable()) {
// Even if this check fails don't return early to allow the best
@@ -14842,8 +14836,8 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS,
if (getLangOpts().OpenCL &&
!getOpenCLOptions().isAvailableOption("cl_khr_fp16", getLangOpts()) &&
LHSType->isHalfType()) {
- Diag(Loc, diag::err_opencl_half_load_store)
- << 1 << LHSType.getUnqualifiedType();
+ Diag(Loc, diag::err_opencl_half_load_store) << 1
+ << LHSType.getUnqualifiedType();
return QualType();
}
@@ -14889,8 +14883,8 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS,
Loc.getLocWithOffset(2) != UO->getSubExpr()->getBeginLoc() &&
UO->getSubExpr()->getBeginLoc().isFileID()) {
Diag(Loc, diag::warn_not_compound_assign)
- << (UO->getOpcode() == UO_Plus ? "+" : "-")
- << SourceRange(UO->getOperatorLoc(), UO->getOperatorLoc());
+ << (UO->getOpcode() == UO_Plus ? "+" : "-")
+ << SourceRange(UO->getOperatorLoc(), UO->getOperatorLoc());
}
}
@@ -15082,7 +15076,7 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op,
// Increment of bool sets it to true, but is deprecated.
S.Diag(OpLoc, S.getLangOpts().CPlusPlus17 ? diag::ext_increment_bool
: diag::warn_increment_bool)
- << Op->getSourceRange();
+ << Op->getSourceRange();
} else if (S.getLangOpts().CPlusPlus && ResType->isEnumeralType()) {
// Error on enum increments and decrements in C++ mode
S.Diag(OpLoc, diag::err_increment_decrement_enum) << IsInc << ResType;
@@ -15107,10 +15101,9 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op,
<< IsInc << Op->getSourceRange();
} else if (ResType->isPlaceholderType()) {
ExprResult PR = S.CheckPlaceholderExpr(Op);
- if (PR.isInvalid())
- return QualType();
- return CheckIncrementDecrementOperand(S, PR.get(), VK, OK, OpLoc, IsInc,
- IsPrefix);
+ if (PR.isInvalid()) return QualType();
+ return CheckIncrementDecrementOperand(S, PR.get(), VK, OK, OpLoc,
+ IsInc, IsPrefix);
} else if (S.getLangOpts().AltiVec && ResType->isVectorType()) {
// OK! ( C/C++ Language Extensions for CBEA(Version 2.6) 10.3 )
} else if (S.getLangOpts().ZVector && ResType->isVectorType() &&
@@ -15122,7 +15115,7 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op,
// OpenCL V1.2 6.3 says dec/inc ops operate on integer vector types.
} else {
S.Diag(OpLoc, diag::err_typecheck_illegal_increment_decrement)
- << ResType << int(IsInc) << Op->getSourceRange();
+ << ResType << int(IsInc) << Op->getSourceRange();
return QualType();
}
// At this point, we know we have a real, complex or pointer type.
@@ -15199,8 +15192,8 @@ static PrimaryObject getPrimaryObject(Expr *E) {
/// Diagnose invalid operand for address of operations.
///
/// \param Type The type of operand which cannot have its address taken.
-static void diagnoseAddressOfInvalidType(Sema &S, SourceLocation Loc, Expr *E,
- unsigned Type) {
+static void diagnoseAddressOfInvalidType(Sema &S, SourceLocation Loc,
+ Expr *E, unsigned Type) {
S.Diag(Loc, diag::err_typecheck_address_of) << Type << E->getSourceRange();
}
@@ -15233,14 +15226,13 @@ bool Sema::CheckUseOfCXXMethodAsAddressOfOperand(SourceLocation OpLoc,
}
QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
- if (const BuiltinType *PTy =
- OrigOp.get()->getType()->getAsPlaceholderType()) {
+ if (const BuiltinType *PTy = OrigOp.get()->getType()->getAsPlaceholderType()){
if (PTy->getKind() == BuiltinType::Overload) {
Expr *E = OrigOp.get()->IgnoreParens();
if (!isa<OverloadExpr>(E)) {
assert(cast<UnaryOperator>(E)->getOpcode() == UO_AddrOf);
Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof_addrof_function)
- << OrigOp.get()->getSourceRange();
+ << OrigOp.get()->getSourceRange();
return QualType();
}
@@ -15248,7 +15240,7 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
if (isa<UnresolvedMemberExpr>(Ovl))
if (!ResolveSingleFunctionTemplateSpecialization(Ovl)) {
Diag(OpLoc, diag::err_invalid_form_pointer_member_function)
- << OrigOp.get()->getSourceRange();
+ << OrigOp.get()->getSourceRange();
return QualType();
}
@@ -15260,13 +15252,12 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
if (PTy->getKind() == BuiltinType::BoundMember) {
Diag(OpLoc, diag::err_invalid_form_pointer_member_function)
- << OrigOp.get()->getSourceRange();
+ << OrigOp.get()->getSourceRange();
return QualType();
}
OrigOp = CheckPlaceholderExpr(OrigOp.get());
- if (OrigOp.isInvalid())
- return QualType();
+ if (OrigOp.isInvalid()) return QualType();
}
if (OrigOp.get()->isTypeDependent())
@@ -15283,7 +15274,7 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
// depending on a vendor implementation. Thus preventing
// taking an address of the capture to avoid invalid AS casts.
if (LangOpts.OpenCL) {
- auto *VarRef = dyn_cast<DeclRefExpr>(op);
+ auto* VarRef = dyn_cast<DeclRefExpr>(op);
if (VarRef && VarRef->refersToEnclosingVariableOrCapture()) {
Diag(op->getExprLoc(), diag::err_opencl_taking_address_capture);
return QualType();
@@ -15292,7 +15283,7 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
if (getLangOpts().C99) {
// Implement C99-only parts of addressof rules.
- if (UnaryOperator *uOp = dyn_cast<UnaryOperator>(op)) {
+ if (UnaryOperator* uOp = dyn_cast<UnaryOperator>(op)) {
if (uOp->getOpcode() == UO_Deref)
// Per C99 6.5.3.2, the address of a deref always returns a valid result
// (assuming the deref expression is valid).
@@ -15331,7 +15322,7 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
// If the underlying expression isn't a decl ref, give up.
if (!isa<DeclRefExpr>(op)) {
Diag(OpLoc, diag::err_invalid_form_pointer_member_function)
- << OrigOp.get()->getSourceRange();
+ << OrigOp.get()->getSourceRange();
return QualType();
}
DeclRefExpr *DRE = cast<DeclRefExpr>(op);
@@ -15386,7 +15377,7 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
AddressOfError = AO_Property_Expansion;
} else {
Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof)
- << op->getType() << op->getSourceRange();
+ << op->getType() << op->getSourceRange();
return QualType();
}
} else if (const auto *DRE = dyn_cast<DeclRefExpr>(op)) {
@@ -15409,7 +15400,8 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
if (const VarDecl *vd = dyn_cast<VarDecl>(dcl)) {
// in C++ it is not error to take address of a register
// variable (c++03 7.1.1P3)
- if (vd->getStorageClass() == SC_Register && !getLangOpts().CPlusPlus) {
+ if (vd->getStorageClass() == SC_Register &&
+ !getLangOpts().CPlusPlus) {
AddressOfError = AO_Register_Variable;
}
} else if (isa<MSPropertyDecl>(dcl)) {
@@ -15433,7 +15425,7 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
if (dcl->getType()->isReferenceType()) {
Diag(OpLoc,
diag::err_cannot_form_pointer_to_member_of_reference_type)
- << dcl->getDeclName() << dcl->getType();
+ << dcl->getDeclName() << dcl->getType();
return QualType();
}
@@ -15504,7 +15496,7 @@ static void RecordModifiableNonNullParam(Sema &S, const Expr *Exp) {
const ParmVarDecl *Param = dyn_cast<ParmVarDecl>(D);
if (!Param)
return;
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Param->getDeclContext()))
+ if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(Param->getDeclContext()))
if (!FD->hasAttr<NonNullAttr>() && !Param->hasAttr<NonNullAttr>())
return;
if (FunctionScopeInfo *FD = S.getCurFunction())
@@ -15524,26 +15516,27 @@ static QualType CheckIndirectionOperand(Sema &S, Expr *Op, ExprValueKind &VK,
if (isa<CXXReinterpretCastExpr>(Op->IgnoreParens())) {
QualType OpOrigType = Op->IgnoreParenCasts()->getType();
- S.CheckCompatibleReinterpretCast(OpOrigType, OpTy, /*IsDereference*/ true,
+ S.CheckCompatibleReinterpretCast(OpOrigType, OpTy, /*IsDereference*/true,
Op->getSourceRange());
}
- if (const PointerType *PT = OpTy->getAs<PointerType>()) {
+ if (const PointerType *PT = OpTy->getAs<PointerType>())
+ {
Result = PT->getPointeeType();
- } else if (const ObjCObjectPointerType *OPT =
- OpTy->getAs<ObjCObjectPointerType>())
+ }
+ else if (const ObjCObjectPointerType *OPT =
+ OpTy->getAs<ObjCObjectPointerType>())
Result = OPT->getPointeeType();
else {
ExprResult PR = S.CheckPlaceholderExpr(Op);
- if (PR.isInvalid())
- return QualType();
+ if (PR.isInvalid()) return QualType();
if (PR.get() != Op)
return CheckIndirectionOperand(S, PR.get(), VK, OpLoc);
}
if (Result.isNull()) {
S.Diag(OpLoc, diag::err_typecheck_indirection_requires_pointer)
- << OpTy << Op->getSourceRange();
+ << OpTy << Op->getSourceRange();
return QualType();
}
@@ -15573,150 +15566,60 @@ static QualType CheckIndirectionOperand(Sema &S, Expr *Op, ExprValueKind &VK,
BinaryOperatorKind Sema::ConvertTokenKindToBinaryOpcode(tok::TokenKind Kind) {
BinaryOperatorKind Opc;
switch (Kind) {
- default:
- llvm_unreachable("Unknown binop!");
- case tok::periodstar:
- Opc = BO_PtrMemD;
- break;
- case tok::arrowstar:
- Opc = BO_PtrMemI;
- break;
- case tok::star:
- Opc = BO_Mul;
- break;
- case tok::slash:
- Opc = BO_Div;
- break;
- case tok::percent:
- Opc = BO_Rem;
- break;
- case tok::plus:
- Opc = BO_Add;
- break;
- case tok::minus:
- Opc = BO_Sub;
- break;
- case tok::lessless:
- Opc = BO_Shl;
- break;
- case tok::greatergreater:
- Opc = BO_Shr;
- break;
- case tok::lessequal:
- Opc = BO_LE;
- break;
- case tok::less:
- Opc = BO_LT;
- break;
- case tok::greaterequal:
- Opc = BO_GE;
- break;
- case tok::greater:
- Opc = BO_GT;
- break;
- case tok::exclaimequal:
- Opc = BO_NE;
- break;
- case tok::equalequal:
- Opc = BO_EQ;
- break;
- case tok::spaceship:
- Opc = BO_Cmp;
- break;
- case tok::amp:
- Opc = BO_And;
- break;
- case tok::caret:
- Opc = BO_Xor;
- break;
- case tok::pipe:
- Opc = BO_Or;
- break;
- case tok::ampamp:
- Opc = BO_LAnd;
- break;
- case tok::pipepipe:
- Opc = BO_LOr;
- break;
- case tok::equal:
- Opc = BO_Assign;
- break;
- case tok::starequal:
- Opc = BO_MulAssign;
- break;
- case tok::slashequal:
- Opc = BO_DivAssign;
- break;
- case tok::percentequal:
- Opc = BO_RemAssign;
- break;
- case tok::plusequal:
- Opc = BO_AddAssign;
- break;
- case tok::minusequal:
- Opc = BO_SubAssign;
- break;
- case tok::lesslessequal:
- Opc = BO_ShlAssign;
- break;
- case tok::greatergreaterequal:
- Opc = BO_ShrAssign;
- break;
- case tok::ampequal:
- Opc = BO_AndAssign;
- break;
- case tok::caretequal:
- Opc = BO_XorAssign;
- break;
- case tok::pipeequal:
- Opc = BO_OrAssign;
- break;
- case tok::comma:
- Opc = BO_Comma;
- break;
+ default: llvm_unreachable("Unknown binop!");
+ case tok::periodstar: Opc = BO_PtrMemD; break;
+ case tok::arrowstar: Opc = BO_PtrMemI; break;
+ case tok::star: Opc = BO_Mul; break;
+ case tok::slash: Opc = BO_Div; break;
+ case tok::percent: Opc = BO_Rem; break;
+ case tok::plus: Opc = BO_Add; break;
+ case tok::minus: Opc = BO_Sub; break;
+ case tok::lessless: Opc = BO_Shl; break;
+ case tok::greatergreater: Opc = BO_Shr; break;
+ case tok::lessequal: Opc = BO_LE; break;
+ case tok::less: Opc = BO_LT; break;
+ case tok::greaterequal: Opc = BO_GE; break;
+ case tok::greater: Opc = BO_GT; break;
+ case tok::exclaimequal: Opc = BO_NE; break;
+ case tok::equalequal: Opc = BO_EQ; break;
+ case tok::spaceship: Opc = BO_Cmp; break;
+ case tok::amp: Opc = BO_And; break;
+ case tok::caret: Opc = BO_Xor; break;
+ case tok::pipe: Opc = BO_Or; break;
+ case tok::ampamp: Opc = BO_LAnd; break;
+ case tok::pipepipe: Opc = BO_LOr; break;
+ case tok::equal: Opc = BO_Assign; break;
+ case tok::starequal: Opc = BO_MulAssign; break;
+ case tok::slashequal: Opc = BO_DivAssign; break;
+ case tok::percentequal: Opc = BO_RemAssign; break;
+ case tok::plusequal: Opc = BO_AddAssign; break;
+ case tok::minusequal: Opc = BO_SubAssign; break;
+ case tok::lesslessequal: Opc = BO_ShlAssign; break;
+ case tok::greatergreaterequal: Opc = BO_ShrAssign; break;
+ case tok::ampequal: Opc = BO_AndAssign; break;
+ case tok::caretequal: Opc = BO_XorAssign; break;
+ case tok::pipeequal: Opc = BO_OrAssign; break;
+ case tok::comma: Opc = BO_Comma; break;
}
return Opc;
}
-static inline UnaryOperatorKind
-ConvertTokenKindToUnaryOpcode(tok::TokenKind Kind) {
+static inline UnaryOperatorKind ConvertTokenKindToUnaryOpcode(
+ tok::TokenKind Kind) {
UnaryOperatorKind Opc;
switch (Kind) {
- default:
- llvm_unreachable("Unknown unary op!");
- case tok::plusplus:
- Opc = UO_PreInc;
- break;
- case tok::minusminus:
- Opc = UO_PreDec;
- break;
- case tok::amp:
- Opc = UO_AddrOf;
- break;
- case tok::star:
- Opc = UO_Deref;
- break;
- case tok::plus:
- Opc = UO_Plus;
- break;
- case tok::minus:
- Opc = UO_Minus;
- break;
- case tok::tilde:
- Opc = UO_Not;
- break;
- case tok::exclaim:
- Opc = UO_LNot;
- break;
- case tok::kw___real:
- Opc = UO_Real;
- break;
- case tok::kw___imag:
- Opc = UO_Imag;
- break;
- case tok::kw___extension__:
- Opc = UO_Extension;
- break;
+ default: llvm_unreachable("Unknown unary op!");
+ case tok::plusplus: Opc = UO_PreInc; break;
+ case tok::minusminus: Opc = UO_PreDec; break;
+ case tok::amp: Opc = UO_AddrOf; break;
+ case tok::star: Opc = UO_Deref; break;
+ case tok::plus: Opc = UO_Plus; break;
+ case tok::minus: Opc = UO_Minus; break;
+ case tok::tilde: Opc = UO_Not; break;
+ case tok::exclaim: Opc = UO_LNot; break;
+ case tok::kw___real: Opc = UO_Real; break;
+ case tok::kw___imag: Opc = UO_Imag; break;
+ case tok::kw___extension__: Opc = UO_Extension; break;
}
return Opc;
}
@@ -15769,13 +15672,14 @@ static void DiagnoseSelfAssignment(Sema &S, Expr *LHSExpr, Expr *RHSExpr,
RHSExpr = RHSExpr->IgnoreParenImpCasts();
const DeclRefExpr *LHSDeclRef = dyn_cast<DeclRefExpr>(LHSExpr);
const DeclRefExpr *RHSDeclRef = dyn_cast<DeclRefExpr>(RHSExpr);
- if (!LHSDeclRef || !RHSDeclRef || LHSDeclRef->getLocation().isMacroID() ||
+ if (!LHSDeclRef || !RHSDeclRef ||
+ LHSDeclRef->getLocation().isMacroID() ||
RHSDeclRef->getLocation().isMacroID())
return;
const ValueDecl *LHSDecl =
- cast<ValueDecl>(LHSDeclRef->getDecl()->getCanonicalDecl());
+ cast<ValueDecl>(LHSDeclRef->getDecl()->getCanonicalDecl());
const ValueDecl *RHSDecl =
- cast<ValueDecl>(RHSDeclRef->getDecl()->getCanonicalDecl());
+ cast<ValueDecl>(RHSDeclRef->getDecl()->getCanonicalDecl());
if (LHSDecl != RHSDecl)
return;
if (LHSDecl->getType().isVolatileQualified())
@@ -15810,7 +15714,8 @@ static void checkObjCPointerIntrospection(Sema &S, ExprResult &L, ExprResult &R,
if (LHS->IgnoreParenCasts()->getType()->isObjCObjectPointerType()) {
ObjCPointerExpr = LHS;
OtherExpr = RHS;
- } else if (RHS->IgnoreParenCasts()->getType()->isObjCObjectPointerType()) {
+ }
+ else if (RHS->IgnoreParenCasts()->getType()->isObjCObjectPointerType()) {
ObjCPointerExpr = RHS;
OtherExpr = LHS;
}
@@ -15833,7 +15738,8 @@ static void checkObjCPointerIntrospection(Sema &S, ExprResult &L, ExprResult &R,
Diag = diag::warn_objc_pointer_masking_performSelector;
}
- S.Diag(OpLoc, Diag) << ObjCPointerExpr->getSourceRange();
+ S.Diag(OpLoc, Diag)
+ << ObjCPointerExpr->getSourceRange();
}
}
@@ -15926,7 +15832,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
}
ExprResult LHS = LHSExpr, RHS = RHSExpr;
- QualType ResultTy; // Result type of the binary operator.
+ QualType ResultTy; // Result type of the binary operator.
// The following two variables are used for compound assignment operators
QualType CompLHSTy; // Type of LHS after promotions for computation
QualType CompResultTy; // Type of computation result
@@ -15953,8 +15859,9 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
// OpenCL special types - image, sampler, pipe, and blocks are to be used
// only with a builtin functions and therefore should be disallowed here.
- if (LHSTy->isImageType() || RHSTy->isImageType() || LHSTy->isSamplerT() ||
- RHSTy->isSamplerT() || LHSTy->isPipeType() || RHSTy->isPipeType() ||
+ if (LHSTy->isImageType() || RHSTy->isImageType() ||
+ LHSTy->isSamplerT() || RHSTy->isSamplerT() ||
+ LHSTy->isPipeType() || RHSTy->isPipeType() ||
LHSTy->isBlockPointerType() || RHSTy->isBlockPointerType()) {
ResultTy = InvalidOperands(OpLoc, LHS, RHS);
return ExprError();
@@ -16003,8 +15910,8 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
break;
case BO_PtrMemD:
case BO_PtrMemI:
- ResultTy =
- CheckPointerToMemberOperands(LHS, RHS, VK, OpLoc, Opc == BO_PtrMemI);
+ ResultTy = CheckPointerToMemberOperands(LHS, RHS, VK, OpLoc,
+ Opc == BO_PtrMemI);
break;
case BO_Mul:
case BO_Div:
@@ -16136,11 +16043,10 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
CheckArrayAccess(LHS.get());
CheckArrayAccess(RHS.get());
- if (const ObjCIsaExpr *OISA =
- dyn_cast<ObjCIsaExpr>(LHS.get()->IgnoreParenCasts())) {
- NamedDecl *ObjectSetClass =
- LookupSingleName(TUScope, &Context.Idents.get("object_setClass"),
- SourceLocation(), LookupOrdinaryName);
+ if (const ObjCIsaExpr *OISA = dyn_cast<ObjCIsaExpr>(LHS.get()->IgnoreParenCasts())) {
+ NamedDecl *ObjectSetClass = LookupSingleName(TUScope,
+ &Context.Idents.get("object_setClass"),
+ SourceLocation(), LookupOrdinaryName);
if (ObjectSetClass && isa<ObjCIsaExpr>(LHS.get())) {
SourceLocation RHSLocEnd = getLocForEndOfToken(RHS.get()->getEndLoc());
Diag(LHS.get()->getExprLoc(), diag::warn_objc_isa_assign)
@@ -16149,10 +16055,12 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
<< FixItHint::CreateReplacement(SourceRange(OISA->getOpLoc(), OpLoc),
",")
<< FixItHint::CreateInsertion(RHSLocEnd, ")");
- } else
+ }
+ else
Diag(LHS.get()->getExprLoc(), diag::warn_objc_isa_assign);
- } else if (const ObjCIvarRefExpr *OIRE =
- dyn_cast<ObjCIvarRefExpr>(LHS.get()->IgnoreParenCasts()))
+ }
+ else if (const ObjCIvarRefExpr *OIRE =
+ dyn_cast<ObjCIvarRefExpr>(LHS.get()->IgnoreParenCasts()))
DiagnoseDirectIsaAccess(*this, OIRE, OpLoc, RHS.get());
// Opc is not a compound assignment if CompResultTy is null.
@@ -16165,8 +16073,8 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
}
// Handle compound assignments.
- if (getLangOpts().CPlusPlus &&
- LHS.get()->getObjectKind() != OK_ObjCProperty) {
+ if (getLangOpts().CPlusPlus && LHS.get()->getObjectKind() !=
+ OK_ObjCProperty) {
VK = VK_LValue;
OK = LHS.get()->getObjectKind();
}
@@ -16219,29 +16127,29 @@ static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperatorKind Opc,
: SourceRange(LHSExpr->getBeginLoc(), RHSBO->getLHS()->getEndLoc());
Self.Diag(OpLoc, diag::warn_precedence_bitwise_rel)
- << DiagRange << BinaryOperator::getOpcodeStr(Opc) << OpStr;
+ << DiagRange << BinaryOperator::getOpcodeStr(Opc) << OpStr;
SuggestParentheses(Self, OpLoc,
- Self.PDiag(diag::note_precedence_silence) << OpStr,
- (isLeftComp ? LHSExpr : RHSExpr)->getSourceRange());
+ Self.PDiag(diag::note_precedence_silence) << OpStr,
+ (isLeftComp ? LHSExpr : RHSExpr)->getSourceRange());
SuggestParentheses(Self, OpLoc,
- Self.PDiag(diag::note_precedence_bitwise_first)
- << BinaryOperator::getOpcodeStr(Opc),
- ParensRange);
+ Self.PDiag(diag::note_precedence_bitwise_first)
+ << BinaryOperator::getOpcodeStr(Opc),
+ ParensRange);
}
/// It accepts a '&&' expr that is inside a '||' one.
/// Emit a diagnostic together with a fixit hint that wraps the '&&' expression
/// in parentheses.
-static void EmitDiagnosticForLogicalAndInLogicalOr(Sema &Self,
- SourceLocation OpLoc,
- BinaryOperator *Bop) {
+static void
+EmitDiagnosticForLogicalAndInLogicalOr(Sema &Self, SourceLocation OpLoc,
+ BinaryOperator *Bop) {
assert(Bop->getOpcode() == BO_LAnd);
Self.Diag(Bop->getOperatorLoc(), diag::warn_logical_and_in_logical_or)
<< Bop->getSourceRange() << OpLoc;
SuggestParentheses(Self, Bop->getOperatorLoc(),
- Self.PDiag(diag::note_precedence_silence)
- << Bop->getOpcodeStr(),
- Bop->getSourceRange());
+ Self.PDiag(diag::note_precedence_silence)
+ << Bop->getOpcodeStr(),
+ Bop->getSourceRange());
}
/// Look for '&&' in the left hand of a '||' expr.
@@ -16286,12 +16194,12 @@ static void DiagnoseBitwiseOpInBitwiseOp(Sema &S, BinaryOperatorKind Opc,
if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(SubExpr)) {
if (Bop->isBitwiseOp() && Bop->getOpcode() < Opc) {
S.Diag(Bop->getOperatorLoc(), diag::warn_bitwise_op_in_bitwise_op)
- << Bop->getOpcodeStr() << BinaryOperator::getOpcodeStr(Opc)
- << Bop->getSourceRange() << OpLoc;
+ << Bop->getOpcodeStr() << BinaryOperator::getOpcodeStr(Opc)
+ << Bop->getSourceRange() << OpLoc;
SuggestParentheses(S, Bop->getOperatorLoc(),
- S.PDiag(diag::note_precedence_silence)
- << Bop->getOpcodeStr(),
- Bop->getSourceRange());
+ S.PDiag(diag::note_precedence_silence)
+ << Bop->getOpcodeStr(),
+ Bop->getSourceRange());
}
}
}
@@ -16304,14 +16212,14 @@ static void DiagnoseAdditionInShift(Sema &S, SourceLocation OpLoc,
S.Diag(Bop->getOperatorLoc(), diag::warn_addition_in_bitshift)
<< Bop->getSourceRange() << OpLoc << Shift << Op;
SuggestParentheses(S, Bop->getOperatorLoc(),
- S.PDiag(diag::note_precedence_silence) << Op,
- Bop->getSourceRange());
+ S.PDiag(diag::note_precedence_silence) << Op,
+ Bop->getSourceRange());
}
}
}
-static void DiagnoseShiftCompare(Sema &S, SourceLocation OpLoc, Expr *LHSExpr,
- Expr *RHSExpr) {
+static void DiagnoseShiftCompare(Sema &S, SourceLocation OpLoc,
+ Expr *LHSExpr, Expr *RHSExpr) {
CXXOperatorCallExpr *OCE = dyn_cast<CXXOperatorCallExpr>(LHSExpr);
if (!OCE)
return;
@@ -16340,28 +16248,27 @@ static void DiagnoseShiftCompare(Sema &S, SourceLocation OpLoc, Expr *LHSExpr,
/// precedence.
static void DiagnoseBinOpPrecedence(Sema &Self, BinaryOperatorKind Opc,
SourceLocation OpLoc, Expr *LHSExpr,
- Expr *RHSExpr) {
+ Expr *RHSExpr){
// Diagnose "arg1 'bitwise' arg2 'eq' arg3".
if (BinaryOperator::isBitwiseOp(Opc))
DiagnoseBitwisePrecedence(Self, Opc, OpLoc, LHSExpr, RHSExpr);
// Diagnose "arg1 & arg2 | arg3"
if ((Opc == BO_Or || Opc == BO_Xor) &&
- !OpLoc.isMacroID() /* Don't warn in macros. */) {
+ !OpLoc.isMacroID()/* Don't warn in macros. */) {
DiagnoseBitwiseOpInBitwiseOp(Self, Opc, OpLoc, LHSExpr);
DiagnoseBitwiseOpInBitwiseOp(Self, Opc, OpLoc, RHSExpr);
}
// Warn about arg1 || arg2 && arg3, as GCC 4.3+ does.
// We don't warn for 'assert(a || b && "bad")' since this is safe.
- if (Opc == BO_LOr && !OpLoc.isMacroID() /* Don't warn in macros. */) {
+ if (Opc == BO_LOr && !OpLoc.isMacroID()/* Don't warn in macros. */) {
DiagnoseLogicalAndInLogicalOrLHS(Self, OpLoc, LHSExpr, RHSExpr);
DiagnoseLogicalAndInLogicalOrRHS(Self, OpLoc, LHSExpr, RHSExpr);
}
- if ((Opc == BO_Shl &&
- LHSExpr->getType()->isIntegralType(Self.getASTContext())) ||
- Opc == BO_Shr) {
+ if ((Opc == BO_Shl && LHSExpr->getType()->isIntegralType(Self.getASTContext()))
+ || Opc == BO_Shr) {
StringRef Shift = BinaryOperator::getOpcodeStr(Opc);
DiagnoseAdditionInShift(Self, OpLoc, LHSExpr, Shift);
DiagnoseAdditionInShift(Self, OpLoc, RHSExpr, Shift);
@@ -16374,7 +16281,8 @@ static void DiagnoseBinOpPrecedence(Sema &Self, BinaryOperatorKind Opc,
}
ExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc,
- tok::TokenKind Kind, Expr *LHSExpr, Expr *RHSExpr) {
+ tok::TokenKind Kind,
+ Expr *LHSExpr, Expr *RHSExpr) {
BinaryOperatorKind Opc = ConvertTokenKindToBinaryOpcode(Kind);
assert(LHSExpr && "ActOnBinOp(): missing left expression");
assert(RHSExpr && "ActOnBinOp(): missing right expression");
@@ -16407,8 +16315,8 @@ void Sema::LookupBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind Opc,
/// Build an overloaded binary operator expression in the given scope.
static ExprResult BuildOverloadedBinOp(Sema &S, Scope *Sc, SourceLocation OpLoc,
- BinaryOperatorKind Opc, Expr *LHS,
- Expr *RHS) {
+ BinaryOperatorKind Opc,
+ Expr *LHS, Expr *RHS) {
switch (Opc) {
case BO_Assign:
// In the non-overloaded case, we warn about self-assignment (x = x) for
@@ -16469,8 +16377,7 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
// that an overload set can be dependently-typed, but it never
// instantiates to having an overloadable type.
ExprResult resolvedRHS = CheckPlaceholderExpr(RHSExpr);
- if (resolvedRHS.isInvalid())
- return ExprError();
+ if (resolvedRHS.isInvalid()) return ExprError();
RHSExpr = resolvedRHS.get();
if (RHSExpr->isTypeDependent() ||
@@ -16501,8 +16408,7 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
}
ExprResult LHS = CheckPlaceholderExpr(LHSExpr);
- if (LHS.isInvalid())
- return ExprError();
+ if (LHS.isInvalid()) return ExprError();
LHSExpr = LHS.get();
}
@@ -16526,8 +16432,7 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
ExprResult resolvedRHS = CheckPlaceholderExpr(RHSExpr);
- if (!resolvedRHS.isUsable())
- return ExprError();
+ if (!resolvedRHS.isUsable()) return ExprError();
RHSExpr = resolvedRHS.get();
}
@@ -16629,11 +16534,10 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
QualType Ty = InputExpr->getType();
// The only legal unary operation for atomics is '&'.
if ((Opc != UO_AddrOf && Ty->isAtomicType()) ||
- // OpenCL special types - image, sampler, pipe, and blocks are to be
- // used only with a builtin functions and therefore should be disallowed
- // here.
- (Ty->isImageType() || Ty->isSamplerT() || Ty->isPipeType() ||
- Ty->isBlockPointerType())) {
+ // OpenCL special types - image, sampler, pipe, and blocks are to be used
+ // only with a builtin functions and therefore should be disallowed here.
+ (Ty->isImageType() || Ty->isSamplerT() || Ty->isPipeType()
+ || Ty->isBlockPointerType())) {
return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
<< InputExpr->getType()
<< Input.get()->getSourceRange());
@@ -16931,15 +16835,15 @@ ExprResult Sema::BuildUnaryOp(Scope *S, SourceLocation OpLoc,
// & gets special logic for several kinds of placeholder.
// The builtin code knows what to do.
- if (Opc == UO_AddrOf && (pty->getKind() == BuiltinType::Overload ||
- pty->getKind() == BuiltinType::UnknownAny ||
- pty->getKind() == BuiltinType::BoundMember))
+ if (Opc == UO_AddrOf &&
+ (pty->getKind() == BuiltinType::Overload ||
+ pty->getKind() == BuiltinType::UnknownAny ||
+ pty->getKind() == BuiltinType::BoundMember))
return CreateBuiltinUnaryOp(OpLoc, Opc, Input);
// Anything else needs to be handled now.
ExprResult Result = CheckPlaceholderExpr(Input);
- if (Result.isInvalid())
- return ExprError();
+ if (Result.isInvalid()) return ExprError();
Input = Result.get();
}
@@ -17077,13 +16981,13 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
// a struct/union/class.
if (!Dependent && !ArgTy->isRecordType())
return ExprError(Diag(BuiltinLoc, diag::err_offsetof_record_type)
- << ArgTy << TypeRange);
+ << ArgTy << TypeRange);
// Type must be complete per C99 7.17p3 because a declaring a variable
// with an incomplete type would be ill-formed.
- if (!Dependent &&
- RequireCompleteType(BuiltinLoc, ArgTy, diag::err_offsetof_incomplete_type,
- TypeRange))
+ if (!Dependent
+ && RequireCompleteType(BuiltinLoc, ArgTy,
+ diag::err_offsetof_incomplete_type, TypeRange))
return ExprError();
bool DidWarnAboutNonPOD = false;
@@ -17097,7 +17001,7 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
// Offset of an array sub-field. TODO: Should we allow vector elements?
if (!CurrentType->isDependentType()) {
const ArrayType *AT = Context.getAsArrayType(CurrentType);
- if (!AT)
+ if(!AT)
return ExprError(Diag(D.getEndLoc(), diag::err_offsetof_array_type)
<< CurrentType);
CurrentType = AT->getElementType();
@@ -17155,10 +17059,9 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
// If type is not a standard-layout class (Clause 9), the results are
// undefined.
if (CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) {
- bool IsSafe =
- LangOpts.CPlusPlus11 ? CRD->isStandardLayout() : CRD->isPOD();
- unsigned DiagID = LangOpts.CPlusPlus11
- ? diag::ext_offsetof_non_standardlayout_type
+ bool IsSafe = LangOpts.CPlusPlus11? CRD->isStandardLayout() : CRD->isPOD();
+ unsigned DiagID =
+ LangOpts.CPlusPlus11? diag::ext_offsetof_non_standardlayout_type
: diag::ext_offsetof_non_pod_type;
if (!IsSafe && !DidWarnAboutNonPOD && !isUnevaluatedContext()) {
@@ -17253,7 +17156,8 @@ ExprResult Sema::ActOnBuiltinOffsetOf(Scope *S, SourceLocation BuiltinLoc,
return BuildBuiltinOffsetOf(BuiltinLoc, ArgTInfo, Desig, RParenLoc);
}
-ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc, Expr *CondExpr,
+ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc,
+ Expr *CondExpr,
Expr *LHSExpr, Expr *RHSExpr,
SourceLocation RPLoc) {
assert((CondExpr && LHSExpr && RHSExpr) && "Missing type argument(s)");
@@ -17339,8 +17243,8 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
// Look for an explicit signature in that function type.
FunctionProtoTypeLoc ExplicitSignature;
- if ((ExplicitSignature =
- Sig->getTypeLoc().getAsAdjusted<FunctionProtoTypeLoc>())) {
+ if ((ExplicitSignature = Sig->getTypeLoc()
+ .getAsAdjusted<FunctionProtoTypeLoc>())) {
// Check whether that explicit signature was synthesized by
// GetTypeForDeclarator. If so, don't save that as part of the
@@ -17379,7 +17283,7 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
}
// Push block parameters from the declarator if we had them.
- SmallVector<ParmVarDecl *, 8> Params;
+ SmallVector<ParmVarDecl*, 8> Params;
if (ExplicitSignature) {
for (unsigned I = 0, E = ExplicitSignature.getNumParams(); I != E; ++I) {
ParmVarDecl *Param = ExplicitSignature.getParam(I);
@@ -17392,8 +17296,8 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
Params.push_back(Param);
}
- // Fake up parameter variables if we have a typedef, like
- // ^ fntype { ... }
+ // Fake up parameter variables if we have a typedef, like
+ // ^ fntype { ... }
} else if (const FunctionProtoType *Fn = T->getAs<FunctionProtoType>()) {
for (const auto &I : Fn->param_types()) {
ParmVarDecl *Param = BuildParmVarDeclForTypedef(
@@ -17438,8 +17342,8 @@ void Sema::ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope) {
PopFunctionScopeInfo();
}
-ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, Stmt *Body,
- Scope *CurScope) {
+ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
+ Stmt *Body, Scope *CurScope) {
// If blocks are disabled, emit an error.
if (!LangOpts.Blocks)
Diag(CaretLoc, diag::err_blocks_disable) << LangOpts.OpenCL;
@@ -17471,8 +17375,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, Stmt *Body,
const FunctionType *FTy = BSI->FunctionType->castAs<FunctionType>();
FunctionType::ExtInfo Ext = FTy->getExtInfo();
- if (NoReturn && !Ext.getNoReturn())
- Ext = Ext.withNoReturn(true);
+ if (NoReturn && !Ext.getNoReturn()) Ext = Ext.withNoReturn(true);
// Turn protoless block types into nullary block types.
if (isa<FunctionNoProtoType>(FTy)) {
@@ -17486,7 +17389,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, Stmt *Body,
(!NoReturn || FTy->getNoReturnAttr())) {
BlockTy = BSI->FunctionType;
- // Otherwise, make the minimal modifications to the function type.
+ // Otherwise, make the minimal modifications to the function type.
} else {
const FunctionProtoType *FPT = cast<FunctionProtoType>(FTy);
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
@@ -17495,7 +17398,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, Stmt *Body,
BlockTy = Context.getFunctionType(RetTy, FPT->getParamTypes(), EPI);
}
- // If we don't have a function type, just build one from nothing.
+ // If we don't have a function type, just build one from nothing.
} else {
FunctionProtoType::ExtProtoInfo EPI;
EPI.ExtInfo = FunctionType::ExtInfo().withNoReturn(NoReturn);
@@ -17506,7 +17409,8 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, Stmt *Body,
BlockTy = Context.getBlockPointerType(BlockTy);
// If needed, diagnose invalid gotos and switches in the block.
- if (getCurFunction()->NeedsScopeChecking() && !PP.isCodeCompletionEnabled())
+ if (getCurFunction()->NeedsScopeChecking() &&
+ !PP.isCodeCompletionEnabled())
DiagnoseInvalidJumps(cast<CompoundStmt>(Body));
BD->setBody(cast<CompoundStmt>(Body));
@@ -17581,9 +17485,9 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, Stmt *Body,
// Build a full-expression copy expression if initialization
// succeeded and used a non-trivial constructor. Recover from
// errors by pretending that the copy isn't necessary.
- if (!Result.isInvalid() && !cast<CXXConstructExpr>(Result.get())
- ->getConstructor()
- ->isTrivial()) {
+ if (!Result.isInvalid() &&
+ !cast<CXXConstructExpr>(Result.get())->getConstructor()
+ ->isTrivial()) {
Result = MaybeCreateExprWithCleanups(Result);
CopyExpr = Result.get();
}
@@ -17640,8 +17544,9 @@ ExprResult Sema::ActOnVAArg(SourceLocation BuiltinLoc, Expr *E, ParsedType Ty,
return BuildVAArgExpr(BuiltinLoc, E, TInfo, RPLoc);
}
-ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc, Expr *E,
- TypeSourceInfo *TInfo, SourceLocation RPLoc) {
+ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc,
+ Expr *E, TypeSourceInfo *TInfo,
+ SourceLocation RPLoc) {
Expr *OrigExpr = E;
VAArgExpr::VarArgKind VAKind = VAArgExpr::VA_Std;
@@ -17663,8 +17568,7 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc, Expr *E,
// as Microsoft ABI on an actual Microsoft platform, where
// __builtin_ms_va_list and __builtin_va_list are the same.)
if (!E->isTypeDependent() && Context.getTargetInfo().hasBuiltinMSVaList() &&
- Context.getTargetInfo().getBuiltinVaListKind() !=
- TargetInfo::CharPtrBuiltinVaList) {
+ Context.getTargetInfo().getBuiltinVaListKind() != TargetInfo::CharPtrBuiltinVaList) {
QualType MSVaListType = Context.getBuiltinMSVaListType();
if (Context.hasSameType(MSVaListType, E->getType())) {
if (CheckForModifiableLvalue(E, BuiltinLoc, *this))
@@ -17735,17 +17639,19 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc, Expr *E,
TInfo->getTypeLoc()))
return ExprError();
- if (RequireNonAbstractType(
- TInfo->getTypeLoc().getBeginLoc(), TInfo->getType(),
- diag::err_second_parameter_to_va_arg_abstract, TInfo->getTypeLoc()))
+ if (RequireNonAbstractType(TInfo->getTypeLoc().getBeginLoc(),
+ TInfo->getType(),
+ diag::err_second_parameter_to_va_arg_abstract,
+ TInfo->getTypeLoc()))
return ExprError();
if (!TInfo->getType().isPODType(Context)) {
Diag(TInfo->getTypeLoc().getBeginLoc(),
TInfo->getType()->isObjCLifetimeType()
- ? diag::warn_second_parameter_to_va_arg_ownership_qualified
- : diag::warn_second_parameter_to_va_arg_not_pod)
- << TInfo->getType() << TInfo->getTypeLoc().getSourceRange();
+ ? diag::warn_second_parameter_to_va_arg_ownership_qualified
+ : diag::warn_second_parameter_to_va_arg_not_pod)
+ << TInfo->getType()
+ << TInfo->getTypeLoc().getSourceRange();
}
if (TInfo->getType()->isArrayType()) {
@@ -17807,11 +17713,11 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc, Expr *E,
if (TInfo->getType()->isSpecificBuiltinType(BuiltinType::Float))
PromoteType = Context.DoubleTy;
if (!PromoteType.isNull())
- DiagRuntimeBehavior(
- TInfo->getTypeLoc().getBeginLoc(), E,
- PDiag(diag::warn_second_parameter_to_va_arg_never_compatible)
- << TInfo->getType() << PromoteType
- << TInfo->getTypeLoc().getSourceRange());
+ DiagRuntimeBehavior(TInfo->getTypeLoc().getBeginLoc(), E,
+ PDiag(diag::warn_second_parameter_to_va_arg_never_compatible)
+ << TInfo->getType()
+ << PromoteType
+ << TInfo->getTypeLoc().getSourceRange());
}
QualType T = TInfo->getType().getNonLValueExprType(Context);
@@ -17974,9 +17880,10 @@ static bool maybeDiagnoseAssignmentToFunction(Sema &S, QualType DstType,
}
bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
- SourceLocation Loc, QualType DstType,
- QualType SrcType, Expr *SrcExpr,
- AssignmentAction Action, bool *Complained) {
+ SourceLocation Loc,
+ QualType DstType, QualType SrcType,
+ Expr *SrcExpr, AssignmentAction Action,
+ bool *Complained) {
if (Complained)
*Complained = false;
@@ -18045,7 +17952,7 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
DiagKind = diag::ext_typecheck_convert_incompatible_pointer;
}
CheckInferredResultType = DstType->isObjCObjectPointerType() &&
- SrcType->isObjCObjectPointerType();
+ SrcType->isObjCObjectPointerType();
if (CheckInferredResultType) {
SrcType = SrcType.getUnqualifiedType();
DstType = DstType.getUnqualifiedType();
@@ -18113,10 +18020,10 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
IsStringLiteralToNonConstPointerConversion(SrcExpr, DstType))
return false;
if (getLangOpts().CPlusPlus) {
- DiagKind = diag::err_typecheck_convert_discards_qualifiers;
+ DiagKind = diag::err_typecheck_convert_discards_qualifiers;
isInvalid = true;
} else {
- DiagKind = diag::ext_typecheck_convert_discards_qualifiers;
+ DiagKind = diag::ext_typecheck_convert_discards_qualifiers;
}
break;
@@ -18143,23 +18050,24 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
case AssignConvertType::IncompatibleObjCQualifiedId: {
if (SrcType->isObjCQualifiedIdType()) {
const ObjCObjectPointerType *srcOPT =
- SrcType->castAs<ObjCObjectPointerType>();
+ SrcType->castAs<ObjCObjectPointerType>();
for (auto *srcProto : srcOPT->quals()) {
PDecl = srcProto;
break;
}
if (const ObjCInterfaceType *IFaceT =
- DstType->castAs<ObjCObjectPointerType>()->getInterfaceType())
+ DstType->castAs<ObjCObjectPointerType>()->getInterfaceType())
IFace = IFaceT->getDecl();
- } else if (DstType->isObjCQualifiedIdType()) {
+ }
+ else if (DstType->isObjCQualifiedIdType()) {
const ObjCObjectPointerType *dstOPT =
- DstType->castAs<ObjCObjectPointerType>();
+ DstType->castAs<ObjCObjectPointerType>();
for (auto *dstProto : dstOPT->quals()) {
PDecl = dstProto;
break;
}
if (const ObjCInterfaceType *IFaceT =
- SrcType->castAs<ObjCObjectPointerType>()->getInterfaceType())
+ SrcType->castAs<ObjCObjectPointerType>()->getInterfaceType())
IFace = IFaceT->getDecl();
}
if (getLangOpts().CPlusPlus) {
@@ -18268,9 +18176,7 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
FDiag << H;
}
- if (MayHaveConvFixit) {
- FDiag << (unsigned)(ConvHints.Kind);
- }
+ if (MayHaveConvFixit) { FDiag << (unsigned) (ConvHints.Kind); }
if (MayHaveFunctionDiff)
HandleFunctionTypeMismatch(FDiag, SecondType, FirstType);
@@ -18283,8 +18189,8 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
<< IFace << PDecl;
if (SecondType == Context.OverloadTy)
- NoteAllOverloadCandidates(OverloadExpr::find(SrcExpr).Expression, FirstType,
- /*TakingAddress=*/true);
+ NoteAllOverloadCandidates(OverloadExpr::find(SrcExpr).Expression,
+ FirstType, /*TakingAddress=*/true);
if (CheckInferredResultType)
ObjC().EmitRelatedResultTypeNote(SrcExpr);
@@ -18298,7 +18204,8 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
return isInvalid;
}
-ExprResult Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
+ExprResult Sema::VerifyIntegerConstantExpression(Expr *E,
+ llvm::APSInt *Result,
AllowFoldKind CanFold) {
class SimpleICEDiagnoser : public VerifyICEDiagnoser {
public:
@@ -18315,7 +18222,8 @@ ExprResult Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
return VerifyIntegerConstantExpression(E, Result, Diagnoser, CanFold);
}
-ExprResult Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
+ExprResult Sema::VerifyIntegerConstantExpression(Expr *E,
+ llvm::APSInt *Result,
unsigned DiagID,
AllowFoldKind CanFold) {
class IDDiagnoser : public VerifyICEDiagnoser {
@@ -18323,7 +18231,7 @@ ExprResult Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
public:
IDDiagnoser(unsigned DiagID)
- : VerifyICEDiagnoser(DiagID == 0), DiagID(DiagID) {}
+ : VerifyICEDiagnoser(DiagID == 0), DiagID(DiagID) { }
SemaDiagnosticBuilder diagnoseNotICE(Sema &S, SourceLocation Loc) override {
return S.Diag(Loc, DiagID);
@@ -18344,9 +18252,10 @@ Sema::VerifyICEDiagnoser::diagnoseFold(Sema &S, SourceLocation Loc) {
return S.Diag(Loc, diag::ext_expr_not_ice) << S.LangOpts.CPlusPlus;
}
-ExprResult Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
- VerifyICEDiagnoser &Diagnoser,
- AllowFoldKind CanFold) {
+ExprResult
+Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
+ VerifyICEDiagnoser &Diagnoser,
+ AllowFoldKind CanFold) {
SourceLocation DiagLoc = E->getBeginLoc();
if (getLangOpts().CPlusPlus11) {
@@ -18358,7 +18267,6 @@ ExprResult Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
ExprResult Converted;
class CXX11ConvertDiagnoser : public ICEConvertDiagnoser {
VerifyICEDiagnoser &BaseDiagnoser;
-
public:
CXX11ConvertDiagnoser(VerifyICEDiagnoser &BaseDiagnoser)
: ICEConvertDiagnoser(/*AllowScopedEnumerations*/ false,
@@ -18370,43 +18278,41 @@ ExprResult Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
return BaseDiagnoser.diagnoseNotICEType(S, Loc, T);
}
- SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
- QualType T) override {
+ SemaDiagnosticBuilder diagnoseIncomplete(
+ Sema &S, SourceLocation Loc, QualType T) override {
return S.Diag(Loc, diag::err_ice_incomplete_type) << T;
}
- SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
- QualType T,
- QualType ConvTy) override {
+ SemaDiagnosticBuilder diagnoseExplicitConv(
+ Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) override {
return S.Diag(Loc, diag::err_ice_explicit_conversion) << T << ConvTy;
}
- SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
- QualType ConvTy) override {
+ SemaDiagnosticBuilder noteExplicitConv(
+ Sema &S, CXXConversionDecl *Conv, QualType ConvTy) override {
return S.Diag(Conv->getLocation(), diag::note_ice_conversion_here)
- << ConvTy->isEnumeralType() << ConvTy;
+ << ConvTy->isEnumeralType() << ConvTy;
}
- SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
- QualType T) override {
+ SemaDiagnosticBuilder diagnoseAmbiguous(
+ Sema &S, SourceLocation Loc, QualType T) override {
return S.Diag(Loc, diag::err_ice_ambiguous_conversion) << T;
}
- SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
- QualType ConvTy) override {
+ SemaDiagnosticBuilder noteAmbiguous(
+ Sema &S, CXXConversionDecl *Conv, QualType ConvTy) override {
return S.Diag(Conv->getLocation(), diag::note_ice_conversion_here)
- << ConvTy->isEnumeralType() << ConvTy;
+ << ConvTy->isEnumeralType() << ConvTy;
}
- SemaDiagnosticBuilder diagnoseConversion(Sema &S, SourceLocation Loc,
- QualType T,
- QualType ConvTy) override {
+ SemaDiagnosticBuilder diagnoseConversion(
+ Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) override {
llvm_unreachable("conversion functions are permitted");
}
} ConvertDiagnoser(Diagnoser);
- Converted =
- PerformContextualImplicitConversion(DiagLoc, E, ConvertDiagnoser);
+ Converted = PerformContextualImplicitConversion(DiagLoc, E,
+ ConvertDiagnoser);
if (Converted.isInvalid())
return Converted;
E = Converted.get();
@@ -18449,7 +18355,7 @@ ExprResult Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
// the caret at its location rather than producing an essentially
// redundant note.
if (Notes.size() == 1 && Notes[0].second.getDiagID() ==
- diag::note_invalid_subexpr_in_const_expr) {
+ diag::note_invalid_subexpr_in_const_expr) {
DiagLoc = Notes[0].first;
Notes.clear();
}
@@ -18509,8 +18415,8 @@ ExprResult Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
// If our only note is the usual "invalid subexpression" note, just point
// the caret at its location rather than producing an essentially
// redundant note.
- if (Notes.size() == 1 &&
- Notes[0].second.getDiagID() == diag::note_invalid_subexpr_in_const_expr) {
+ if (Notes.size() == 1 && Notes[0].second.getDiagID() ==
+ diag::note_invalid_subexpr_in_const_expr) {
DiagLoc = Notes[0].first;
Notes.clear();
}
@@ -18535,57 +18441,58 @@ ExprResult Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
}
namespace {
-// Handle the case where we conclude a expression which we speculatively
-// considered to be unevaluated is actually evaluated.
-class TransformToPE : public TreeTransform<TransformToPE> {
- typedef TreeTransform<TransformToPE> BaseTransform;
+ // Handle the case where we conclude a expression which we speculatively
+ // considered to be unevaluated is actually evaluated.
+ class TransformToPE : public TreeTransform<TransformToPE> {
+ typedef TreeTransform<TransformToPE> BaseTransform;
-public:
- TransformToPE(Sema &SemaRef) : BaseTransform(SemaRef) {}
+ public:
+ TransformToPE(Sema &SemaRef) : BaseTransform(SemaRef) { }
- // Make sure we redo semantic analysis
- bool AlwaysRebuild() { return true; }
- bool ReplacingOriginal() { return true; }
+ // Make sure we redo semantic analysis
+ bool AlwaysRebuild() { return true; }
+ bool ReplacingOriginal() { return true; }
- // We need to special-case DeclRefExprs referring to FieldDecls which
- // are not part of a member pointer formation; normal TreeTransforming
- // doesn't catch this case because of the way we represent them in the AST.
- // FIXME: This is a bit ugly; is it really the best way to handle this
- // case?
- //
- // Error on DeclRefExprs referring to FieldDecls.
- ExprResult TransformDeclRefExpr(DeclRefExpr *E) {
- if (isa<FieldDecl>(E->getDecl()) && !SemaRef.isUnevaluatedContext())
- return SemaRef.Diag(E->getLocation(),
- diag::err_invalid_non_static_member_use)
- << E->getDecl() << E->getSourceRange();
+ // We need to special-case DeclRefExprs referring to FieldDecls which
+ // are not part of a member pointer formation; normal TreeTransforming
+ // doesn't catch this case because of the way we represent them in the AST.
+ // FIXME: This is a bit ugly; is it really the best way to handle this
+ // case?
+ //
+ // Error on DeclRefExprs referring to FieldDecls.
+ ExprResult TransformDeclRefExpr(DeclRefExpr *E) {
+ if (isa<FieldDecl>(E->getDecl()) &&
+ !SemaRef.isUnevaluatedContext())
+ return SemaRef.Diag(E->getLocation(),
+ diag::err_invalid_non_static_member_use)
+ << E->getDecl() << E->getSourceRange();
- return BaseTransform::TransformDeclRefExpr(E);
- }
+ return BaseTransform::TransformDeclRefExpr(E);
+ }
- // Exception: filter out member pointer formation
- ExprResult TransformUnaryOperator(UnaryOperator *E) {
- if (E->getOpcode() == UO_AddrOf && E->getType()->isMemberPointerType())
- return E;
+ // Exception: filter out member pointer formation
+ ExprResult TransformUnaryOperator(UnaryOperator *E) {
+ if (E->getOpcode() == UO_AddrOf && E->getType()->isMemberPointerType())
+ return E;
- return BaseTransform::TransformUnaryOperator(E);
- }
+ return BaseTransform::TransformUnaryOperator(E);
+ }
- // The body of a lambda-expression is in a separate expression evaluation
- // context so never needs to be transformed.
- // FIXME: Ideally we wouldn't transform the closure type either, and would
- // just recreate the capture expressions and lambda expression.
- StmtResult TransformLambdaBody(LambdaExpr *E, Stmt *Body) {
- return SkipLambdaBody(E, Body);
- }
-};
-} // namespace
+ // The body of a lambda-expression is in a separate expression evaluation
+ // context so never needs to be transformed.
+ // FIXME: Ideally we wouldn't transform the closure type either, and would
+ // just recreate the capture expressions and lambda expression.
+ StmtResult TransformLambdaBody(LambdaExpr *E, Stmt *Body) {
+ return SkipLambdaBody(E, Body);
+ }
+ };
+}
ExprResult Sema::TransformToPotentiallyEvaluated(Expr *E) {
assert(isUnevaluatedContext() &&
"Should only transform unevaluated expressions");
ExprEvalContexts.back().Context =
- ExprEvalContexts[ExprEvalContexts.size() - 2].Context;
+ ExprEvalContexts[ExprEvalContexts.size()-2].Context;
if (isUnevaluatedContext())
return E;
return TransformToPE(*this).TransformExpr(E);
@@ -18600,7 +18507,8 @@ TypeSourceInfo *Sema::TransformToPotentiallyEvaluated(TypeSourceInfo *TInfo) {
return TransformToPE(*this).TransformType(TInfo);
}
-void Sema::PushExpressionEvaluationContext(
+void
+Sema::PushExpressionEvaluationContext(
ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl,
ExpressionEvaluationContextRecord::ExpressionKind ExprContext) {
ExprEvalContexts.emplace_back(NewContext, ExprCleanupObjects.size(), Cleanup,
@@ -18628,7 +18536,8 @@ void Sema::PushExpressionEvaluationContext(
std::swap(MaybeODRUseExprs, ExprEvalContexts.back().SavedMaybeODRUseExprs);
}
-void Sema::PushExpressionEvaluationContext(
+void
+Sema::PushExpressionEvaluationContext(
ExpressionEvaluationContext NewContext, ReuseLambdaContextDecl_t,
ExpressionEvaluationContextRecord::ExpressionKind ExprContext) {
Decl *ClosureContextDecl = ExprEvalContexts.back().ManglingContextDecl;
@@ -18895,7 +18804,7 @@ static void RemoveNestedImmediateInvocation(
SmallVector<Sema::ImmediateInvocationCandidate,
4>::reverse_iterator Current)
: Base(SemaRef), DRSet(DR), IISet(II), CurrentII(Current) {}
- void RemoveImmediateInvocation(ConstantExpr *E) {
+ void RemoveImmediateInvocation(ConstantExpr* E) {
auto It = std::find_if(CurrentII, IISet.rend(),
[E](Sema::ImmediateInvocationCandidate Elem) {
return Elem.getPointer() == E;
@@ -19104,7 +19013,7 @@ HandleImmediateInvocations(Sema &SemaRef,
}
void Sema::PopExpressionEvaluationContext() {
- ExpressionEvaluationContextRecord &Rec = ExprEvalContexts.back();
+ ExpressionEvaluationContextRecord& Rec = ExprEvalContexts.back();
if (!Rec.Lambdas.empty()) {
using ExpressionKind = ExpressionEvaluationContextRecord::ExpressionKind;
if (!getLangOpts().CPlusPlus20 &&
@@ -19164,7 +19073,7 @@ void Sema::PopExpressionEvaluationContext() {
Cleanup = Rec.ParentCleanup;
CleanupVarDeclMarking();
std::swap(MaybeODRUseExprs, Rec.SavedMaybeODRUseExprs);
- // Otherwise, merge the contexts together.
+ // Otherwise, merge the contexts together.
} else {
Cleanup.mergeFrom(Rec.ParentCleanup);
MaybeODRUseExprs.insert_range(Rec.SavedMaybeODRUseExprs);
@@ -19177,9 +19086,9 @@ void Sema::PopExpressionEvaluationContext() {
}
void Sema::DiscardCleanupsInEvaluationContext() {
- ExprCleanupObjects.erase(ExprCleanupObjects.begin() +
- ExprEvalContexts.back().NumCleanupObjects,
- ExprCleanupObjects.end());
+ ExprCleanupObjects.erase(
+ ExprCleanupObjects.begin() + ExprEvalContexts.back().NumCleanupObjects,
+ ExprCleanupObjects.end());
Cleanup.reset();
MaybeODRUseExprs.clear();
}
@@ -19200,27 +19109,27 @@ static bool isPotentiallyConstantEvaluatedContext(Sema &SemaRef) {
/// C++2a [expr.const]p12:
// An expression or conversion is potentially constant evaluated if it is
switch (SemaRef.ExprEvalContexts.back().Context) {
- case Sema::ExpressionEvaluationContext::ConstantEvaluated:
- case Sema::ExpressionEvaluationContext::ImmediateFunctionContext:
-
- // -- a manifestly constant-evaluated expression,
- case Sema::ExpressionEvaluationContext::PotentiallyEvaluated:
- case Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed:
- case Sema::ExpressionEvaluationContext::DiscardedStatement:
- // -- a potentially-evaluated expression,
- case Sema::ExpressionEvaluationContext::UnevaluatedList:
- // -- an immediate subexpression of a braced-init-list,
-
- // -- [FIXME] an expression of the form & cast-expression that occurs
- // within a templated entity
- // -- a subexpression of one of the above that is not a subexpression of
- // a nested unevaluated operand.
- return true;
+ case Sema::ExpressionEvaluationContext::ConstantEvaluated:
+ case Sema::ExpressionEvaluationContext::ImmediateFunctionContext:
+
+ // -- a manifestly constant-evaluated expression,
+ case Sema::ExpressionEvaluationContext::PotentiallyEvaluated:
+ case Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed:
+ case Sema::ExpressionEvaluationContext::DiscardedStatement:
+ // -- a potentially-evaluated expression,
+ case Sema::ExpressionEvaluationContext::UnevaluatedList:
+ // -- an immediate subexpression of a braced-init-list,
+
+ // -- [FIXME] an expression of the form & cast-expression that occurs
+ // within a templated entity
+ // -- a subexpression of one of the above that is not a subexpression of
+ // a nested unevaluated operand.
+ return true;
- case Sema::ExpressionEvaluationContext::Unevaluated:
- case Sema::ExpressionEvaluationContext::UnevaluatedAbstract:
- // Expressions in this context are never evaluated.
- return false;
+ case Sema::ExpressionEvaluationContext::Unevaluated:
+ case Sema::ExpressionEvaluationContext::UnevaluatedAbstract:
+ // Expressions in this context are never evaluated.
+ return false;
}
llvm_unreachable("Invalid context");
}
@@ -19498,7 +19407,7 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func,
PointOfInstantiation = Loc;
if (auto *MSI = Func->getMemberSpecializationInfo())
MSI->setPointOfInstantiation(Loc);
- // FIXME: Notify listener.
+ // FIXME: Notify listener.
else
Func->setTemplateSpecializationKind(TSK, PointOfInstantiation);
} else if (TSK != TSK_ImplicitInstantiation) {
@@ -19591,7 +19500,8 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func,
if (!Func->isDefined() && !Func->isInAnotherModuleUnit()) {
if (mightHaveNonExternalLinkage(Func))
UndefinedButUsed.insert(std::make_pair(Func->getCanonicalDecl(), Loc));
- else if (Func->getMostRecentDecl()->isInlined() && !LangOpts.GNUInline &&
+ else if (Func->getMostRecentDecl()->isInlined() &&
+ !LangOpts.GNUInline &&
!Func->getMostRecentDecl()->hasAttr<GNUInlineAttr>())
UndefinedButUsed.insert(std::make_pair(Func->getCanonicalDecl(), Loc));
else if (isExternalWithNoLinkageType(Func))
@@ -19721,7 +19631,8 @@ static void diagnoseUncapturableValueReferenceOrBinding(Sema &S,
// If the parameter still belongs to the translation unit, then
// we're actually just using one parameter in the declaration of
// the next.
- if (isa<ParmVarDecl>(var) && isa<TranslationUnitDecl>(VarDC))
+ if (isa<ParmVarDecl>(var) &&
+ isa<TranslationUnitDecl>(VarDC))
return;
// For C code, don't diagnose about capture if we're not actually in code
@@ -19746,8 +19657,9 @@ static void diagnoseUncapturableValueReferenceOrBinding(Sema &S,
}
S.Diag(loc, diag::err_reference_to_local_in_enclosing_context)
- << var << ValueKind << ContextKind << VarDC;
- S.Diag(var->getLocation(), diag::note_entity_declared_at) << var;
+ << var << ValueKind << ContextKind << VarDC;
+ S.Diag(var->getLocation(), diag::note_entity_declared_at)
+ << var;
// FIXME: Add additional diagnostic info about class etc. which prevents
// capture.
@@ -19908,7 +19820,8 @@ static bool captureInBlock(BlockScopeInfo *BSI, ValueDecl *Var,
if (!Invalid &&
CaptureType.getObjCLifetime() == Qualifiers::OCL_Autoreleasing) {
if (BuildAndDiagnose) {
- S.Diag(Loc, diag::err_arc_autoreleasing_capture) << /*block*/ 0;
+ S.Diag(Loc, diag::err_arc_autoreleasing_capture)
+ << /*block*/ 0;
S.Diag(Var->getLocation(), diag::note_previous_decl) << Var;
Invalid = true;
} else {
@@ -20039,7 +19952,7 @@ static bool captureInLambda(LambdaScopeInfo *LSI, ValueDecl *Var,
// captured entity is a reference to a function, the
// corresponding data member is also a reference to a
// function. - end note ]
- if (const ReferenceType *RefType = CaptureType->getAs<ReferenceType>()) {
+ if (const ReferenceType *RefType = CaptureType->getAs<ReferenceType>()){
if (!RefType->getPointeeType()->isFunctionType())
CaptureType = RefType->getPointeeType();
}
@@ -20050,7 +19963,7 @@ static bool captureInLambda(LambdaScopeInfo *LSI, ValueDecl *Var,
if (BuildAndDiagnose) {
S.Diag(Loc, diag::err_arc_autoreleasing_capture) << /*lambda*/ 1;
S.Diag(Var->getLocation(), diag::note_previous_decl)
- << Var->getDeclName();
+ << Var->getDeclName();
Invalid = true;
} else {
return false;
@@ -20238,8 +20151,7 @@ bool Sema::tryCaptureVariable(
assert(VD && "Cannot capture a null variable");
const unsigned MaxFunctionScopesIndex = FunctionScopeIndexToStopAt
- ? *FunctionScopeIndexToStopAt
- : FunctionScopes.size() - 1;
+ ? *FunctionScopeIndexToStopAt : FunctionScopes.size() - 1;
// We need to sync up the Declaration Context with the
// FunctionScopeIndexToStopAt
if (FunctionScopeIndexToStopAt) {
@@ -20324,7 +20236,7 @@ bool Sema::tryCaptureVariable(
return true;
}
- FunctionScopeInfo *FSI = FunctionScopes[FunctionScopesIndex];
+ FunctionScopeInfo *FSI = FunctionScopes[FunctionScopesIndex];
CapturingScopeInfo *CSI = cast<CapturingScopeInfo>(FSI);
// Check whether we've already captured it.
@@ -20472,13 +20384,13 @@ bool Sema::tryCaptureVariable(
// If the variable had already been captured previously, we start capturing
// at the lambda nested within that one.
bool Invalid = false;
- for (unsigned I = ++FunctionScopesIndex, N = MaxFunctionScopesIndex + 1;
- I != N; ++I) {
+ for (unsigned I = ++FunctionScopesIndex, N = MaxFunctionScopesIndex + 1; I != N;
+ ++I) {
CapturingScopeInfo *CSI = cast<CapturingScopeInfo>(FunctionScopes[I]);
- // Certain capturing entities (lambdas, blocks etc.) are not allowed to
- // capture certain types of variables (unnamed, variably modified types
- // etc.) so check for eligibility.
+ // Certain capturing entities (lambdas, blocks etc.) are not allowed to capture
+ // certain types of variables (unnamed, variably modified types etc.)
+ // so check for eligibility.
if (!Invalid)
Invalid =
!isVariableCapturable(CSI, Var, ExprLoc, BuildAndDiagnose, *this);
@@ -20489,12 +20401,10 @@ bool Sema::tryCaptureVariable(
return true;
if (BlockScopeInfo *BSI = dyn_cast<BlockScopeInfo>(CSI)) {
- Invalid =
- !captureInBlock(BSI, Var, ExprLoc, BuildAndDiagnose, CaptureType,
- DeclRefType, Nested, *this, Invalid);
+ Invalid = !captureInBlock(BSI, Var, ExprLoc, BuildAndDiagnose, CaptureType,
+ DeclRefType, Nested, *this, Invalid);
Nested = true;
- } else if (CapturedRegionScopeInfo *RSI =
- dyn_cast<CapturedRegionScopeInfo>(CSI)) {
+ } else if (CapturedRegionScopeInfo *RSI = dyn_cast<CapturedRegionScopeInfo>(CSI)) {
Invalid = !captureInCapturedRegion(
RSI, Var, ExprLoc, BuildAndDiagnose, CaptureType, DeclRefType, Nested,
Kind, /*IsTopScope*/ I == N - 1, *this, Invalid);
@@ -20519,8 +20429,8 @@ bool Sema::tryCaptureVariable(ValueDecl *Var, SourceLocation Loc,
QualType CaptureType;
QualType DeclRefType;
return tryCaptureVariable(Var, Loc, Kind, EllipsisLoc,
- /*BuildAndDiagnose=*/true, CaptureType, DeclRefType,
- nullptr);
+ /*BuildAndDiagnose=*/true, CaptureType,
+ DeclRefType, nullptr);
}
bool Sema::NeedToCaptureVariable(ValueDecl *Var, SourceLocation Loc) {
@@ -20554,24 +20464,23 @@ namespace {
class CopiedTemplateArgs {
bool HasArgs;
TemplateArgumentListInfo TemplateArgStorage;
-
public:
- template <typename RefExpr>
+ template<typename RefExpr>
CopiedTemplateArgs(RefExpr *E) : HasArgs(E->hasExplicitTemplateArgs()) {
if (HasArgs)
E->copyTemplateArgumentsInto(TemplateArgStorage);
}
- operator TemplateArgumentListInfo *()
+ operator TemplateArgumentListInfo*()
#ifdef __has_cpp_attribute
#if __has_cpp_attribute(clang::lifetimebound)
- [[clang::lifetimebound]]
+ [[clang::lifetimebound]]
#endif
#endif
{
return HasArgs ? &TemplateArgStorage : nullptr;
}
};
-} // namespace
+}
/// Walk the set of potential results of an expression and mark them all as
/// non-odr-uses if they satisfy the side-conditions of the NonOdrUseReason.
@@ -20763,7 +20672,7 @@ static ExprResult rebuildPotentialResultsAsNonOdrUsed(Sema &S, Expr *E,
if (!Sub.isUsable())
return Sub;
BO->setLHS(Sub.get());
- // -- If e is a comma expression, ...
+ // -- If e is a comma expression, ...
} else if (BO->getOpcode() == BO_Comma) {
ExprResult Sub = Rebuild(RHS);
if (!Sub.isUsable())
@@ -20960,8 +20869,8 @@ void Sema::CleanupVarDeclMarking() {
for (Expr *E : LocalMaybeODRUseExprs) {
if (auto *DRE = dyn_cast<DeclRefExpr>(E)) {
- MarkVarDeclODRUsed(cast<VarDecl>(DRE->getDecl()), DRE->getLocation(),
- *this);
+ MarkVarDeclODRUsed(cast<VarDecl>(DRE->getDecl()),
+ DRE->getLocation(), *this);
} else if (auto *ME = dyn_cast<MemberExpr>(E)) {
MarkVarDeclODRUsed(cast<VarDecl>(ME->getMemberDecl()), ME->getMemberLoc(),
*this);
@@ -21082,7 +20991,7 @@ static void DoMarkVarDeclReferenced(
PointOfInstantiation = Loc;
if (MSI)
MSI->setPointOfInstantiation(PointOfInstantiation);
- // FIXME: Notify listener.
+ // FIXME: Notify listener.
else
Var->setTemplateSpecializationKind(TSK, PointOfInstantiation);
}
@@ -21108,8 +21017,8 @@ static void DoMarkVarDeclReferenced(
else if (auto *ME = dyn_cast_or_null<MemberExpr>(E))
ME->setMemberDecl(ME->getMemberDecl());
} else if (FirstInstantiation) {
- SemaRef.PendingInstantiations.push_back(
- std::make_pair(Var, PointOfInstantiation));
+ SemaRef.PendingInstantiations
+ .push_back(std::make_pair(Var, PointOfInstantiation));
} else {
bool Inserted = false;
for (auto &I : SemaRef.SavedPendingInstantiations) {
@@ -21131,8 +21040,8 @@ static void DoMarkVarDeclReferenced(
// no direct way to avoid enqueueing the pending instantiation
// multiple times.
if (isa<VarTemplateSpecializationDecl>(Var) && !Inserted)
- SemaRef.PendingInstantiations.push_back(
- std::make_pair(Var, PointOfInstantiation));
+ SemaRef.PendingInstantiations
+ .push_back(std::make_pair(Var, PointOfInstantiation));
}
}
}
@@ -21306,8 +21215,8 @@ MarkExprReferenced(Sema &SemaRef, SourceLocation Loc, Decl *D, Expr *E,
if (!MD)
return;
// Only attempt to devirtualize if this is truly a virtual call.
- bool IsVirtualCall =
- MD->isVirtual() && ME->performsVirtualDispatch(SemaRef.getLangOpts());
+ bool IsVirtualCall = MD->isVirtual() &&
+ ME->performsVirtualDispatch(SemaRef.getLangOpts());
if (!IsVirtualCall)
return;
@@ -21388,13 +21297,13 @@ void Sema::MarkAnyDeclReferenced(SourceLocation Loc, Decl *D,
}
namespace {
-// Mark all of the declarations used by a type as referenced.
-// FIXME: Not fully implemented yet! We need to have a better understanding
-// of when we're entering a context we should not recurse into.
-// FIXME: This is and EvaluatedExprMarker are more-or-less equivalent to
-// TreeTransforms rebuilding the type in a new context. Rather than
-// duplicating the TreeTransform logic, we should consider reusing it here.
-// Currently that causes problems when rebuilding LambdaExprs.
+ // Mark all of the declarations used by a type as referenced.
+ // FIXME: Not fully implemented yet! We need to have a better understanding
+ // of when we're entering a context we should not recurse into.
+ // FIXME: This is and EvaluatedExprMarker are more-or-less equivalent to
+ // TreeTransforms rebuilding the type in a new context. Rather than
+ // duplicating the TreeTransform logic, we should consider reusing it here.
+ // Currently that causes problems when rebuilding LambdaExprs.
class MarkReferencedDecls : public DynamicRecursiveASTVisitor {
Sema &S;
SourceLocation Loc;
@@ -21404,7 +21313,7 @@ class MarkReferencedDecls : public DynamicRecursiveASTVisitor {
bool TraverseTemplateArgument(const TemplateArgument &Arg) override;
};
-} // namespace
+}
bool MarkReferencedDecls::TraverseTemplateArgument(
const TemplateArgument &Arg) {
@@ -21477,8 +21386,9 @@ class EvaluatedExprMarker : public UsedDeclVisitor<EvaluatedExprMarker> {
};
} // namespace
-void Sema::MarkDeclarationsReferencedInExpr(Expr *E, bool SkipLocalVariables,
- ArrayRef<const Expr *> StopAt) {
+void Sema::MarkDeclarationsReferencedInExpr(Expr *E,
+ bool SkipLocalVariables,
+ ArrayRef<const Expr*> StopAt) {
EvaluatedExprMarker(*this, SkipLocalVariables, StopAt).Visit(E);
}
@@ -21543,7 +21453,7 @@ bool Sema::DiagIfReachable(SourceLocation Loc, ArrayRef<const Stmt *> Stmts,
/// behavior of a program, such as passing a non-POD value through an ellipsis.
/// Failure to do so will likely result in spurious diagnostics or failures
/// during overload resolution or within sizeof/alignof/typeof/typeid.
-bool Sema::DiagRuntimeBehavior(SourceLocation Loc, ArrayRef<const Stmt *> Stmts,
+bool Sema::DiagRuntimeBehavior(SourceLocation Loc, ArrayRef<const Stmt*> Stmts,
const PartialDiagnostic &PD) {
if (ExprEvalContexts.back().isDiscardedStatementContext())
@@ -21596,12 +21506,12 @@ bool Sema::CheckCallReturnType(QualType ReturnType, SourceLocation Loc,
public:
CallReturnIncompleteDiagnoser(FunctionDecl *FD, CallExpr *CE)
- : FD(FD), CE(CE) {}
+ : FD(FD), CE(CE) { }
void diagnose(Sema &S, SourceLocation Loc, QualType T) override {
if (!FD) {
S.Diag(Loc, diag::err_call_incomplete_return)
- << T << CE->getSourceRange();
+ << T << CE->getSourceRange();
return;
}
@@ -21633,8 +21543,8 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) {
IsOrAssign = Op->getOpcode() == BO_OrAssign;
// Greylist some idioms by putting them into a warning subcategory.
- if (ObjCMessageExpr *ME =
- dyn_cast<ObjCMessageExpr>(Op->getRHS()->IgnoreParenCasts())) {
+ if (ObjCMessageExpr *ME
+ = dyn_cast<ObjCMessageExpr>(Op->getRHS()->IgnoreParenCasts())) {
Selector Sel = ME->getSelector();
// self = [<foo> init...]
@@ -21665,15 +21575,15 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) {
SourceLocation Open = E->getBeginLoc();
SourceLocation Close = getLocForEndOfToken(E->getSourceRange().getEnd());
Diag(Loc, diag::note_condition_assign_silence)
- << FixItHint::CreateInsertion(Open, "(")
- << FixItHint::CreateInsertion(Close, ")");
+ << FixItHint::CreateInsertion(Open, "(")
+ << FixItHint::CreateInsertion(Close, ")");
if (IsOrAssign)
Diag(Loc, diag::note_condition_or_assign_to_comparison)
- << FixItHint::CreateReplacement(Loc, "!=");
+ << FixItHint::CreateReplacement(Loc, "!=");
else
Diag(Loc, diag::note_condition_assign_to_comparison)
- << FixItHint::CreateReplacement(Loc, "==");
+ << FixItHint::CreateReplacement(Loc, "==");
}
void Sema::DiagnoseEqualityWithExtraParens(ParenExpr *ParenE) {
@@ -21691,17 +21601,17 @@ void Sema::DiagnoseEqualityWithExtraParens(ParenExpr *ParenE) {
if (BinaryOperator *opE = dyn_cast<BinaryOperator>(E))
if (opE->getOpcode() == BO_EQ &&
- opE->getLHS()->IgnoreParenImpCasts()->isModifiableLvalue(Context) ==
- Expr::MLV_Valid) {
+ opE->getLHS()->IgnoreParenImpCasts()->isModifiableLvalue(Context)
+ == Expr::MLV_Valid) {
SourceLocation Loc = opE->getOperatorLoc();
Diag(Loc, diag::warn_equality_with_extra_parens) << E->getSourceRange();
SourceRange ParenERange = ParenE->getSourceRange();
Diag(Loc, diag::note_equality_comparison_silence)
- << FixItHint::CreateRemoval(ParenERange.getBegin())
- << FixItHint::CreateRemoval(ParenERange.getEnd());
+ << FixItHint::CreateRemoval(ParenERange.getBegin())
+ << FixItHint::CreateRemoval(ParenERange.getEnd());
Diag(Loc, diag::note_equality_comparison_to_assign)
- << FixItHint::CreateReplacement(Loc, "=");
+ << FixItHint::CreateReplacement(Loc, "=");
}
}
@@ -21712,8 +21622,7 @@ ExprResult Sema::CheckBooleanCondition(SourceLocation Loc, Expr *E,
DiagnoseEqualityWithExtraParens(parenE);
ExprResult result = CheckPlaceholderExpr(E);
- if (result.isInvalid())
- return ExprError();
+ if (result.isInvalid()) return ExprError();
E = result.get();
if (!E->isTypeDependent()) {
@@ -21731,7 +21640,7 @@ ExprResult Sema::CheckBooleanCondition(SourceLocation Loc, Expr *E,
QualType T = E->getType();
if (!T->isScalarType()) { // C99 6.8.4.1p1
Diag(Loc, diag::err_typecheck_statement_requires_scalar)
- << T << E->getSourceRange();
+ << T << E->getSourceRange();
return ExprError();
}
CheckBoolLikeConversion(E, Loc);
@@ -21779,182 +21688,190 @@ Sema::ConditionResult Sema::ActOnCondition(Scope *S, SourceLocation Loc,
}
namespace {
-/// A visitor for rebuilding a call to an __unknown_any expression
-/// to have an appropriate type.
-struct RebuildUnknownAnyFunction
+ /// A visitor for rebuilding a call to an __unknown_any expression
+ /// to have an appropriate type.
+ struct RebuildUnknownAnyFunction
: StmtVisitor<RebuildUnknownAnyFunction, ExprResult> {
- Sema &S;
+ Sema &S;
- RebuildUnknownAnyFunction(Sema &S) : S(S) {}
+ RebuildUnknownAnyFunction(Sema &S) : S(S) {}
- ExprResult VisitStmt(Stmt *S) { llvm_unreachable("unexpected statement!"); }
+ ExprResult VisitStmt(Stmt *S) {
+ llvm_unreachable("unexpected statement!");
+ }
- ExprResult VisitExpr(Expr *E) {
- S.Diag(E->getExprLoc(), diag::err_unsupported_unknown_any_call)
+ ExprResult VisitExpr(Expr *E) {
+ S.Diag(E->getExprLoc(), diag::err_unsupported_unknown_any_call)
<< E->getSourceRange();
- return ExprError();
- }
-
- /// Rebuild an expression which simply semantically wraps another
- /// expression which it shares the type and value kind of.
- template <class T> ExprResult rebuildSugarExpr(T *E) {
- ExprResult SubResult = Visit(E->getSubExpr());
- if (SubResult.isInvalid())
return ExprError();
+ }
- Expr *SubExpr = SubResult.get();
- E->setSubExpr(SubExpr);
- E->setType(SubExpr->getType());
- E->setValueKind(SubExpr->getValueKind());
- assert(E->getObjectKind() == OK_Ordinary);
- return E;
- }
+ /// Rebuild an expression which simply semantically wraps another
+ /// expression which it shares the type and value kind of.
+ template <class T> ExprResult rebuildSugarExpr(T *E) {
+ ExprResult SubResult = Visit(E->getSubExpr());
+ if (SubResult.isInvalid()) return ExprError();
- ExprResult VisitParenExpr(ParenExpr *E) { return rebuildSugarExpr(E); }
+ Expr *SubExpr = SubResult.get();
+ E->setSubExpr(SubExpr);
+ E->setType(SubExpr->getType());
+ E->setValueKind(SubExpr->getValueKind());
+ assert(E->getObjectKind() == OK_Ordinary);
+ return E;
+ }
- ExprResult VisitUnaryExtension(UnaryOperator *E) {
- return rebuildSugarExpr(E);
- }
+ ExprResult VisitParenExpr(ParenExpr *E) {
+ return rebuildSugarExpr(E);
+ }
- ExprResult VisitUnaryAddrOf(UnaryOperator *E) {
- ExprResult SubResult = Visit(E->getSubExpr());
- if (SubResult.isInvalid())
- return ExprError();
+ ExprResult VisitUnaryExtension(UnaryOperator *E) {
+ return rebuildSugarExpr(E);
+ }
- Expr *SubExpr = SubResult.get();
- E->setSubExpr(SubExpr);
- E->setType(S.Context.getPointerType(SubExpr->getType()));
- assert(E->isPRValue());
- assert(E->getObjectKind() == OK_Ordinary);
- return E;
- }
+ ExprResult VisitUnaryAddrOf(UnaryOperator *E) {
+ ExprResult SubResult = Visit(E->getSubExpr());
+ if (SubResult.isInvalid()) return ExprError();
- ExprResult resolveDecl(Expr *E, ValueDecl *VD) {
- if (!isa<FunctionDecl>(VD))
- return VisitExpr(E);
+ Expr *SubExpr = SubResult.get();
+ E->setSubExpr(SubExpr);
+ E->setType(S.Context.getPointerType(SubExpr->getType()));
+ assert(E->isPRValue());
+ assert(E->getObjectKind() == OK_Ordinary);
+ return E;
+ }
- E->setType(VD->getType());
+ ExprResult resolveDecl(Expr *E, ValueDecl *VD) {
+ if (!isa<FunctionDecl>(VD)) return VisitExpr(E);
- assert(E->isPRValue());
- if (S.getLangOpts().CPlusPlus &&
- !(isa<CXXMethodDecl>(VD) && cast<CXXMethodDecl>(VD)->isInstance()))
- E->setValueKind(VK_LValue);
+ E->setType(VD->getType());
- return E;
- }
+ assert(E->isPRValue());
+ if (S.getLangOpts().CPlusPlus &&
+ !(isa<CXXMethodDecl>(VD) &&
+ cast<CXXMethodDecl>(VD)->isInstance()))
+ E->setValueKind(VK_LValue);
- ExprResult VisitMemberExpr(MemberExpr *E) {
- return resolveDecl(E, E->getMemberDecl());
- }
+ return E;
+ }
- ExprResult VisitDeclRefExpr(DeclRefExpr *E) {
- return resolveDecl(E, E->getDecl());
- }
-};
-} // namespace
+ ExprResult VisitMemberExpr(MemberExpr *E) {
+ return resolveDecl(E, E->getMemberDecl());
+ }
+
+ ExprResult VisitDeclRefExpr(DeclRefExpr *E) {
+ return resolveDecl(E, E->getDecl());
+ }
+ };
+}
/// Given a function expression of unknown-any type, try to rebuild it
/// to have a function type.
static ExprResult rebuildUnknownAnyFunction(Sema &S, Expr *FunctionExpr) {
ExprResult Result = RebuildUnknownAnyFunction(S).Visit(FunctionExpr);
- if (Result.isInvalid())
- return ExprError();
+ if (Result.isInvalid()) return ExprError();
return S.DefaultFunctionArrayConversion(Result.get());
}
namespace {
-/// A visitor for rebuilding an expression of type __unknown_anytype
-/// into one which resolves the type directly on the referring
-/// expression. Strict preservation of the original source
-/// structure is not a goal.
-struct RebuildUnknownAnyExpr : StmtVisitor<RebuildUnknownAnyExpr, ExprResult> {
+ /// A visitor for rebuilding an expression of type __unknown_anytype
+ /// into one which resolves the type directly on the referring
+ /// expression. Strict preservation of the original source
+ /// structure is not a goal.
+ struct RebuildUnknownAnyExpr
+ : StmtVisitor<RebuildUnknownAnyExpr, ExprResult> {
- Sema &S;
+ Sema &S;
- /// The current destination type.
- QualType DestType;
+ /// The current destination type.
+ QualType DestType;
- RebuildUnknownAnyExpr(Sema &S, QualType CastType)
+ RebuildUnknownAnyExpr(Sema &S, QualType CastType)
: S(S), DestType(CastType) {}
- ExprResult VisitStmt(Stmt *S) { llvm_unreachable("unexpected statement!"); }
+ ExprResult VisitStmt(Stmt *S) {
+ llvm_unreachable("unexpected statement!");
+ }
- ExprResult VisitExpr(Expr *E) {
- S.Diag(E->getExprLoc(), diag::err_unsupported_unknown_any_expr)
+ ExprResult VisitExpr(Expr *E) {
+ S.Diag(E->getExprLoc(), diag::err_unsupported_unknown_any_expr)
<< E->getSourceRange();
- return ExprError();
- }
+ return ExprError();
+ }
- ExprResult VisitCallExpr(CallExpr *E);
- ExprResult VisitObjCMessageExpr(ObjCMessageExpr *E);
+ ExprResult VisitCallExpr(CallExpr *E);
+ ExprResult VisitObjCMessageExpr(ObjCMessageExpr *E);
- /// Rebuild an expression which simply semantically wraps another
- /// expression which it shares the type and value kind of.
- template <class T> ExprResult rebuildSugarExpr(T *E) {
- ExprResult SubResult = Visit(E->getSubExpr());
- if (SubResult.isInvalid())
- return ExprError();
- Expr *SubExpr = SubResult.get();
- E->setSubExpr(SubExpr);
- E->setType(SubExpr->getType());
- E->setValueKind(SubExpr->getValueKind());
- assert(E->getObjectKind() == OK_Ordinary);
- return E;
- }
+ /// Rebuild an expression which simply semantically wraps another
+ /// expression which it shares the type and value kind of.
+ template <class T> ExprResult rebuildSugarExpr(T *E) {
+ ExprResult SubResult = Visit(E->getSubExpr());
+ if (SubResult.isInvalid()) return ExprError();
+ Expr *SubExpr = SubResult.get();
+ E->setSubExpr(SubExpr);
+ E->setType(SubExpr->getType());
+ E->setValueKind(SubExpr->getValueKind());
+ assert(E->getObjectKind() == OK_Ordinary);
+ return E;
+ }
- ExprResult VisitParenExpr(ParenExpr *E) { return rebuildSugarExpr(E); }
+ ExprResult VisitParenExpr(ParenExpr *E) {
+ return rebuildSugarExpr(E);
+ }
- ExprResult VisitUnaryExtension(UnaryOperator *E) {
- return rebuildSugarExpr(E);
- }
+ ExprResult VisitUnaryExtension(UnaryOperator *E) {
+ return rebuildSugarExpr(E);
+ }
- ExprResult VisitUnaryAddrOf(UnaryOperator *E) {
- const PointerType *Ptr = DestType->getAs<PointerType>();
- if (!Ptr) {
- S.Diag(E->getOperatorLoc(), diag::err_unknown_any_addrof)
+ ExprResult VisitUnaryAddrOf(UnaryOperator *E) {
+ const PointerType *Ptr = DestType->getAs<PointerType>();
+ if (!Ptr) {
+ S.Diag(E->getOperatorLoc(), diag::err_unknown_any_addrof)
<< E->getSourceRange();
- return ExprError();
- }
+ return ExprError();
+ }
- if (isa<CallExpr>(E->getSubExpr())) {
- S.Diag(E->getOperatorLoc(), diag::err_unknown_any_addrof_call)
+ if (isa<CallExpr>(E->getSubExpr())) {
+ S.Diag(E->getOperatorLoc(), diag::err_unknown_any_addrof_call)
<< E->getSourceRange();
- return ExprError();
- }
+ return ExprError();
+ }
- assert(E->isPRValue());
- assert(E->getObjectKind() == OK_Ordinary);
- E->setType(DestType);
+ assert(E->isPRValue());
+ assert(E->getObjectKind() == OK_Ordinary);
+ E->setType(DestType);
- // Build the sub-expression as if it were an object of the pointee type.
- DestType = Ptr->getPointeeType();
- ExprResult SubResult = Visit(E->getSubExpr());
- if (SubResult.isInvalid())
- return ExprError();
- E->setSubExpr(SubResult.get());
- return E;
- }
+ // Build the sub-expression as if it were an object of the pointee type.
+ DestType = Ptr->getPointeeType();
+ ExprResult SubResult = Visit(E->getSubExpr());
+ if (SubResult.isInvalid()) return ExprError();
+ E->setSubExpr(SubResult.get());
+ return E;
+ }
- ExprResult VisitImplicitCastExpr(ImplicitCastExpr *E);
+ ExprResult VisitImplicitCastExpr(ImplicitCastExpr *E);
- ExprResult resolveDecl(Expr *E, ValueDecl *VD);
+ ExprResult resolveDecl(Expr *E, ValueDecl *VD);
- ExprResult VisitMemberExpr(MemberExpr *E) {
- return resolveDecl(E, E->getMemberDecl());
- }
+ ExprResult VisitMemberExpr(MemberExpr *E) {
+ return resolveDecl(E, E->getMemberDecl());
+ }
- ExprResult VisitDeclRefExpr(DeclRefExpr *E) {
- return resolveDecl(E, E->getDecl());
- }
-};
-} // namespace
+ ExprResult VisitDeclRefExpr(DeclRefExpr *E) {
+ return resolveDecl(E, E->getDecl());
+ }
+ };
+}
/// Rebuilds a call expression which yielded __unknown_anytype.
ExprResult RebuildUnknownAnyExpr::VisitCallExpr(CallExpr *E) {
Expr *CalleeExpr = E->getCallee();
- enum FnKind { FK_MemberFunction, FK_FunctionPointer, FK_BlockPointer };
+ enum FnKind {
+ FK_MemberFunction,
+ FK_FunctionPointer,
+ FK_BlockPointer
+ };
FnKind Kind;
QualType CalleeType = CalleeExpr->getType();
@@ -21978,7 +21895,8 @@ ExprResult RebuildUnknownAnyExpr::VisitCallExpr(CallExpr *E) {
if (Kind == FK_BlockPointer)
diagID = diag::err_block_returning_array_function;
- S.Diag(E->getExprLoc(), diagID) << DestType->isFunctionType() << DestType;
+ S.Diag(E->getExprLoc(), diagID)
+ << DestType->isFunctionType() << DestType;
return ExprError();
}
@@ -22021,7 +21939,8 @@ ExprResult RebuildUnknownAnyExpr::VisitCallExpr(CallExpr *E) {
DestType = S.Context.getFunctionType(DestType, ParamTypes,
Proto->getExtProtoInfo());
} else {
- DestType = S.Context.getFunctionNoProtoType(DestType, FnType->getExtInfo());
+ DestType = S.Context.getFunctionNoProtoType(DestType,
+ FnType->getExtInfo());
}
// Rebuild the appropriate pointer-to-function type.
@@ -22041,8 +21960,7 @@ ExprResult RebuildUnknownAnyExpr::VisitCallExpr(CallExpr *E) {
// Finally, we can recurse.
ExprResult CalleeResult = Visit(CalleeExpr);
- if (!CalleeResult.isUsable())
- return ExprError();
+ if (!CalleeResult.isUsable()) return ExprError();
E->setCallee(CalleeResult.get());
// Bind a temporary if necessary.
@@ -22053,7 +21971,7 @@ ExprResult RebuildUnknownAnyExpr::VisitObjCMessageExpr(ObjCMessageExpr *E) {
// Verify that this is a legal result type of a call.
if (DestType->isArrayType() || DestType->isFunctionType()) {
S.Diag(E->getExprLoc(), diag::err_func_returning_array_function)
- << DestType->isFunctionType() << DestType;
+ << DestType->isFunctionType() << DestType;
return ExprError();
}
@@ -22082,8 +22000,7 @@ ExprResult RebuildUnknownAnyExpr::VisitImplicitCastExpr(ImplicitCastExpr *E) {
DestType = DestType->castAs<PointerType>()->getPointeeType();
ExprResult Result = Visit(E->getSubExpr());
- if (!Result.isUsable())
- return ExprError();
+ if (!Result.isUsable()) return ExprError();
E->setSubExpr(Result.get());
return E;
@@ -22099,8 +22016,7 @@ ExprResult RebuildUnknownAnyExpr::VisitImplicitCastExpr(ImplicitCastExpr *E) {
DestType = S.Context.getLValueReferenceType(DestType);
ExprResult Result = Visit(E->getSubExpr());
- if (!Result.isUsable())
- return ExprError();
+ if (!Result.isUsable()) return ExprError();
E->setSubExpr(Result.get());
return E;
@@ -22120,15 +22036,14 @@ ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *E, ValueDecl *VD) {
if (const PointerType *Ptr = Type->getAs<PointerType>()) {
DestType = Ptr->getPointeeType();
ExprResult Result = resolveDecl(E, VD);
- if (Result.isInvalid())
- return ExprError();
+ if (Result.isInvalid()) return ExprError();
return S.ImpCastExprToType(Result.get(), Type, CK_FunctionToPointerDecay,
VK_PRValue);
}
if (!Type->isFunctionType()) {
S.Diag(E->getExprLoc(), diag::err_unknown_any_function)
- << VD << E->getSourceRange();
+ << VD << E->getSourceRange();
return ExprError();
}
if (const FunctionProtoType *FT = Type->getAs<FunctionProtoType>()) {
@@ -22137,11 +22052,9 @@ ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *E, ValueDecl *VD) {
// type. See the lengthy commentary in that routine.
QualType FDT = FD->getType();
const FunctionType *FnType = FDT->castAs<FunctionType>();
- const FunctionProtoType *Proto =
- dyn_cast_or_null<FunctionProtoType>(FnType);
+ const FunctionProtoType *Proto = dyn_cast_or_null<FunctionProtoType>(FnType);
DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E);
- if (DRE && Proto && Proto->getParamTypes().empty() &&
- Proto->isVariadic()) {
+ if (DRE && Proto && Proto->getParamTypes().empty() && Proto->isVariadic()) {
SourceLocation Loc = FD->getLocation();
FunctionDecl *NewFD = FunctionDecl::Create(
S.Context, FD->getDeclContext(), Loc, Loc,
@@ -22153,9 +22066,10 @@ ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *E, ValueDecl *VD) {
if (FD->getQualifier())
NewFD->setQualifierInfo(FD->getQualifierLoc());
- SmallVector<ParmVarDecl *, 16> Params;
+ SmallVector<ParmVarDecl*, 16> Params;
for (const auto &AI : FT->param_types()) {
- ParmVarDecl *Param = S.BuildParmVarDeclForTypedef(FD, Loc, AI);
+ ParmVarDecl *Param =
+ S.BuildParmVarDeclForTypedef(FD, Loc, AI);
Param->setScopeInfo(0, Params.size());
Params.push_back(Param);
}
@@ -22175,20 +22089,20 @@ ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *E, ValueDecl *VD) {
if (!S.getLangOpts().CPlusPlus)
ValueKind = VK_PRValue;
- // - variables
+ // - variables
} else if (isa<VarDecl>(VD)) {
if (const ReferenceType *RefTy = Type->getAs<ReferenceType>()) {
Type = RefTy->getPointeeType();
} else if (Type->isFunctionType()) {
S.Diag(E->getExprLoc(), diag::err_unknown_any_var_function_type)
- << VD << E->getSourceRange();
+ << VD << E->getSourceRange();
return ExprError();
}
- // - nothing else
+ // - nothing else
} else {
S.Diag(E->getExprLoc(), diag::err_unsupported_unknown_any_decl)
- << VD << E->getSourceRange();
+ << VD << E->getSourceRange();
return ExprError();
}
@@ -22211,8 +22125,7 @@ ExprResult Sema::checkUnknownAnyCast(SourceRange TypeRange, QualType CastType,
// Rewrite the casted expression from scratch.
ExprResult result = RebuildUnknownAnyExpr(*this, CastType).Visit(CastExpr);
- if (!result.isUsable())
- return ExprError();
+ if (!result.isUsable()) return ExprError();
CastExpr = result.get();
VK = CastExpr->getValueKind();
@@ -22225,15 +22138,14 @@ ExprResult Sema::forceUnknownAnyToType(Expr *E, QualType ToType) {
return RebuildUnknownAnyExpr(*this, ToType).Visit(E);
}
-ExprResult Sema::checkUnknownAnyArg(SourceLocation callLoc, Expr *arg,
- QualType ¶mType) {
+ExprResult Sema::checkUnknownAnyArg(SourceLocation callLoc,
+ Expr *arg, QualType ¶mType) {
// If the syntactic form of the argument is not an explicit cast of
// any sort, just do default argument promotion.
ExplicitCastExpr *castArg = dyn_cast<ExplicitCastExpr>(arg->IgnoreParens());
if (!castArg) {
ExprResult result = DefaultArgumentPromotion(arg);
- if (result.isInvalid())
- return ExprError();
+ if (result.isInvalid()) return ExprError();
paramType = result.get()->getType();
return result;
}
@@ -22244,8 +22156,8 @@ ExprResult Sema::checkUnknownAnyArg(SourceLocation callLoc, Expr *arg,
// Copy-initialize a parameter of that type.
InitializedEntity entity =
- InitializedEntity::InitializeParameter(Context, paramType,
- /*consumed*/ false);
+ InitializedEntity::InitializeParameter(Context, paramType,
+ /*consumed*/ false);
return PerformCopyInitialization(entity, callLoc, arg);
}
@@ -22276,13 +22188,13 @@ static ExprResult diagnoseUnknownAnyExpr(Sema &S, Expr *E) {
d = msg->getMethodDecl();
if (!d) {
S.Diag(loc, diag::err_uncasted_send_to_unknown_any_method)
- << static_cast<unsigned>(msg->isClassMessage()) << msg->getSelector()
- << orig->getSourceRange();
+ << static_cast<unsigned>(msg->isClassMessage()) << msg->getSelector()
+ << orig->getSourceRange();
return ExprError();
}
} else {
S.Diag(E->getExprLoc(), diag::err_unsupported_unknown_any_expr)
- << E->getSourceRange();
+ << E->getSourceRange();
return ExprError();
}
@@ -22294,8 +22206,7 @@ static ExprResult diagnoseUnknownAnyExpr(Sema &S, Expr *E) {
ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
const BuiltinType *placeholderType = E->getType()->getAsPlaceholderType();
- if (!placeholderType)
- return E;
+ if (!placeholderType) return E;
switch (placeholderType->getKind()) {
case BuiltinType::UnresolvedTemplate: {
@@ -22476,15 +22387,18 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
case BuiltinType::OMPIterator:
return ExprError(Diag(E->getBeginLoc(), diag::err_omp_iterator_use));
- // Everything else should be impossible.
-#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
+ // Everything else should be impossible.
+#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
case BuiltinType::Id:
#include "clang/Basic/OpenCLImageTypes.def"
-#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) case BuiltinType::Id:
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
+ case BuiltinType::Id:
#include "clang/Basic/OpenCLExtensionTypes.def"
-#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#define SVE_TYPE(Name, Id, SingletonId) \
+ case BuiltinType::Id:
#include "clang/Basic/AArch64ACLETypes.def"
-#define PPC_VECTOR_TYPE(Name, Id, Size) case BuiltinType::Id:
+#define PPC_VECTOR_TYPE(Name, Id, Size) \
+ case BuiltinType::Id:
#include "clang/Basic/PPCTypes.def"
#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
#include "clang/Basic/RISCVVTypes.def"
More information about the cfe-commits
mailing list