aboutsummaryrefslogtreecommitdiff
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/cmake/caches/Release.cmake8
-rw-r--r--clang/include/clang/Basic/BuiltinsARM.def4
-rw-r--r--clang/include/clang/Basic/DiagnosticDriverKinds.td3
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--clang/include/clang/Driver/Options.td8
-rw-r--r--clang/lib/AST/ByteCode/Interp.cpp115
-rw-r--r--clang/lib/AST/ByteCode/Interp.h26
-rw-r--r--clang/lib/AST/ByteCode/InterpBuiltin.cpp2
-rw-r--r--clang/lib/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.cpp89
-rw-r--r--clang/lib/CodeGen/BackendUtil.cpp8
-rw-r--r--clang/lib/Driver/ToolChains/Flang.cpp7
-rw-r--r--clang/lib/Format/WhitespaceManager.cpp25
-rw-r--r--clang/lib/Sema/SemaARM.cpp15
-rw-r--r--clang/test/AST/ByteCode/builtin-functions.cpp5
-rw-r--r--clang/test/AST/ByteCode/c.c6
-rw-r--r--clang/test/AST/ByteCode/records.cpp21
-rw-r--r--clang/test/AST/ByteCode/unions.cpp9
-rw-r--r--clang/test/CodeGen/builtins-arm-exclusive.c46
-rw-r--r--clang/test/CodeGenCXX/builtins-arm-exclusive.cpp32
-rw-r--r--clang/test/DebugInfo/ObjC/property-2.m18
-rw-r--r--clang/test/DebugInfo/ObjC/property-auto-synth.m13
-rw-r--r--clang/test/DebugInfo/ObjC/property-basic.m20
-rw-r--r--clang/test/DebugInfo/ObjC/property-explicit-accessors.m34
-rw-r--r--clang/test/DebugInfo/ObjC/property-explicit-ivar.m22
-rw-r--r--clang/test/DebugInfo/ObjC/property.m15
-rw-r--r--clang/test/DebugInfo/ObjC/property2.m15
-rw-r--r--clang/test/DebugInfo/ObjC/property4.m18
-rw-r--r--clang/test/DebugInfo/ObjC/property5.m33
-rw-r--r--clang/test/DebugInfo/ObjCXX/lit.local.cfg5
-rw-r--r--clang/test/Sema/builtins-arm-exclusive-124.c24
-rw-r--r--clang/test/Sema/builtins-arm-exclusive-4.c18
-rw-r--r--clang/test/Sema/builtins-arm-exclusive-none.c20
-rw-r--r--clang/test/Sema/builtins-arm-exclusive.c53
-rw-r--r--clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp211
-rw-r--r--clang/unittests/Format/FormatTest.cpp19
35 files changed, 782 insertions, 187 deletions
diff --git a/clang/cmake/caches/Release.cmake b/clang/cmake/caches/Release.cmake
index 82bfdc0..25f79701 100644
--- a/clang/cmake/caches/Release.cmake
+++ b/clang/cmake/caches/Release.cmake
@@ -30,12 +30,18 @@ endfunction()
#
# cmake -D LLVM_RELEASE_ENABLE_PGO=ON -C Release.cmake
-set (DEFAULT_PROJECTS "clang;lld;lldb;clang-tools-extra;polly;mlir;flang")
+set (DEFAULT_PROJECTS "clang;lld;lldb;clang-tools-extra;polly;mlir")
# bolt only supports ELF, so only enable it for Linux.
if (${CMAKE_HOST_SYSTEM_NAME} MATCHES "Linux")
list(APPEND DEFAULT_PROJECTS "bolt")
endif()
+# Don't build flang on Darwin due to:
+# https://github.com/llvm/llvm-project/issues/160546
+if (NOT ${CMAKE_HOST_SYSTEM_NAME} MATCHES "Darwin")
+ list(APPEND DEFAULT_PROJECTS "flang")
+endif()
+
set (DEFAULT_RUNTIMES "compiler-rt;libcxx")
if (NOT WIN32)
list(APPEND DEFAULT_RUNTIMES "libcxxabi" "libunwind")
diff --git a/clang/include/clang/Basic/BuiltinsARM.def b/clang/include/clang/Basic/BuiltinsARM.def
index 2592e25..cdcc0d0 100644
--- a/clang/include/clang/Basic/BuiltinsARM.def
+++ b/clang/include/clang/Basic/BuiltinsARM.def
@@ -125,8 +125,8 @@ BUILTIN(__builtin_arm_cls, "UiZUi", "nc")
BUILTIN(__builtin_arm_cls64, "UiWUi", "nc")
// Store and load exclusive
-BUILTIN(__builtin_arm_ldrexd, "LLUiv*", "")
-BUILTIN(__builtin_arm_strexd, "iLLUiv*", "")
+BUILTIN(__builtin_arm_ldrexd, "v.", "t")
+BUILTIN(__builtin_arm_strexd, "i.", "t")
BUILTIN(__builtin_arm_ldrex, "v.", "t")
BUILTIN(__builtin_arm_ldaex, "v.", "t")
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 0581bf3..83980e3 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -133,6 +133,9 @@ def warn_drv_unsupported_option_for_offload_arch_req_feature : Warning<
def warn_drv_unsupported_option_for_target : Warning<
"ignoring '%0' option as it is not currently supported for target '%1'">,
InGroup<OptionIgnored>;
+def warn_drv_invalid_argument_for_flang : Warning<
+ "'%0' is not valid for Fortran">,
+ InGroup<OptionIgnored>;
def warn_drv_unsupported_option_for_flang : Warning<
"the argument '%0' is not supported for option '%1'. Mapping to '%1%2'">,
InGroup<OptionIgnored>;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 6087893..4e369be 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9405,7 +9405,7 @@ def err_atomic_exclusive_builtin_pointer_size : Error<
"%select{|,| or }7%select{|8}8"
" byte type (%0 invalid)">;
def err_atomic_exclusive_builtin_pointer_size_none : Error<
- "load and store exclusive builtins are not available on this architecture">;
+ "%select{|eight-byte }0load and store exclusive builtins are not available on this architecture">;
def err_atomic_builtin_ext_int_size : Error<
"atomic memory operand must have a power-of-two size">;
def err_atomic_builtin_bit_int_prohibit : Error<
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 93aeb22..bca8b26 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1955,7 +1955,7 @@ defm borland_extensions : BoolFOption<"borland-extensions",
"Accept non-standard constructs supported by the Borland compiler">,
NegFlag<SetFalse>>;
def fbuiltin : Flag<["-"], "fbuiltin">, Group<f_Group>,
- Visibility<[ClangOption, CLOption, DXCOption]>;
+ Visibility<[ClangOption, CLOption, DXCOption, FlangOption, FC1Option]>;
def fbuiltin_module_map : Flag <["-"], "fbuiltin-module-map">, Group<f_Group>,
Flags<[]>, HelpText<"Load the clang builtins module map file.">;
defm caret_diagnostics : BoolFOption<"caret-diagnostics",
@@ -3563,7 +3563,7 @@ def fno_assume_sane_operator_new : Flag<["-"], "fno-assume-sane-operator-new">,
Visibility<[ClangOption, CC1Option]>,
MarshallingInfoNegativeFlag<CodeGenOpts<"AssumeSaneOperatorNew">>;
def fno_builtin : Flag<["-"], "fno-builtin">, Group<f_Group>,
- Visibility<[ClangOption, CC1Option, CLOption, DXCOption]>,
+ Visibility<[ClangOption, CC1Option, CLOption, DXCOption, FlangOption, FC1Option]>,
HelpText<"Disable implicit builtin knowledge of functions">;
def fno_builtin_ : Joined<["-"], "fno-builtin-">, Group<f_Group>,
Visibility<[ClangOption, CC1Option, CLOption, DXCOption]>,
@@ -4372,7 +4372,7 @@ def fno_trigraphs : Flag<["-"], "fno-trigraphs">, Group<f_Group>,
HelpText<"Do not process trigraph sequences">,
Visibility<[ClangOption, CC1Option]>;
def funique_source_file_names: Flag<["-"], "funique-source-file-names">, Group<f_Group>,
- HelpText<"Allow the compiler to assume that each translation unit has a unique "
+ HelpText<"Allow the compiler to assume that each translation unit has a unique "
"source file identifier (see -funique-source-file-identifier) at link time">;
def fno_unique_source_file_names: Flag<["-"], "fno-unique-source-file-names">;
def unique_source_file_identifier_EQ: Joined<["-"], "funique-source-file-identifier=">, Group<f_Group>,
@@ -7191,7 +7191,7 @@ defm android_pad_segment : BooleanFFlag<"android-pad-segment">, Group<f_Group>;
def shared_libflangrt : Flag<["-"], "shared-libflangrt">,
HelpText<"Link the flang-rt shared library">, Group<Link_Group>,
Visibility<[FlangOption]>, Flags<[NoArgumentUnused]>;
-def static_libflangrt : Flag<["-"], "static-libflangrt">,
+def static_libflangrt : Flag<["-"], "static-libflangrt">,
HelpText<"Link the flang-rt static library">, Group<Link_Group>,
Visibility<[FlangOption]>, Flags<[NoArgumentUnused]>;
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index 910868b..d640be0 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -870,7 +870,8 @@ bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
return true;
}
-bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
+bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
+ bool WillBeActivated) {
if (!Ptr.isBlockPointer() || Ptr.isZero())
return false;
@@ -885,7 +886,7 @@ bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
return false;
if (!CheckRange(S, OpPC, Ptr, AK_Assign))
return false;
- if (!CheckActive(S, OpPC, Ptr, AK_Assign))
+ if (!WillBeActivated && !CheckActive(S, OpPC, Ptr, AK_Assign))
return false;
if (!CheckGlobal(S, OpPC, Ptr))
return false;
@@ -932,6 +933,15 @@ static bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) {
if (F->isValid() && F->hasBody() && F->isConstexpr())
return true;
+ const FunctionDecl *DiagDecl = F->getDecl();
+ const FunctionDecl *Definition = nullptr;
+ DiagDecl->getBody(Definition);
+
+ if (!Definition && S.checkingPotentialConstantExpression() &&
+ DiagDecl->isConstexpr()) {
+ return false;
+ }
+
// Implicitly constexpr.
if (F->isLambdaStaticInvoker())
return true;
@@ -939,7 +949,7 @@ static bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) {
// Bail out if the function declaration itself is invalid. We will
// have produced a relevant diagnostic while parsing it, so just
// note the problematic sub-expression.
- if (F->getDecl()->isInvalidDecl())
+ if (DiagDecl->isInvalidDecl())
return Invalid(S, OpPC);
// Diagnose failed assertions specially.
@@ -957,64 +967,61 @@ static bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) {
}
}
- if (S.getLangOpts().CPlusPlus11) {
- const FunctionDecl *DiagDecl = F->getDecl();
-
- // Invalid decls have been diagnosed before.
- if (DiagDecl->isInvalidDecl())
- return false;
+ if (!S.getLangOpts().CPlusPlus11) {
+ S.FFDiag(S.Current->getLocation(OpPC),
+ diag::note_invalid_subexpr_in_const_expr);
+ return false;
+ }
- // If this function is not constexpr because it is an inherited
- // non-constexpr constructor, diagnose that directly.
- const auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl);
- if (CD && CD->isInheritingConstructor()) {
- const auto *Inherited = CD->getInheritedConstructor().getConstructor();
- if (!Inherited->isConstexpr())
- DiagDecl = CD = Inherited;
- }
+ // Invalid decls have been diagnosed before.
+ if (DiagDecl->isInvalidDecl())
+ return false;
- // Silently reject constructors of invalid classes. The invalid class
- // has been rejected elsewhere before.
- if (CD && CD->getParent()->isInvalidDecl())
- return false;
+ // If this function is not constexpr because it is an inherited
+ // non-constexpr constructor, diagnose that directly.
+ const auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl);
+ if (CD && CD->isInheritingConstructor()) {
+ const auto *Inherited = CD->getInheritedConstructor().getConstructor();
+ if (!Inherited->isConstexpr())
+ DiagDecl = CD = Inherited;
+ }
- // FIXME: If DiagDecl is an implicitly-declared special member function
- // or an inheriting constructor, we should be much more explicit about why
- // it's not constexpr.
- if (CD && CD->isInheritingConstructor()) {
- S.FFDiag(S.Current->getLocation(OpPC),
- diag::note_constexpr_invalid_inhctor, 1)
- << CD->getInheritedConstructor().getConstructor()->getParent();
- S.Note(DiagDecl->getLocation(), diag::note_declared_at);
- } else {
- // Don't emit anything if the function isn't defined and we're checking
- // for a constant expression. It might be defined at the point we're
- // actually calling it.
- bool IsExtern = DiagDecl->getStorageClass() == SC_Extern;
- bool IsDefined = F->isDefined();
- if (!IsDefined && !IsExtern && DiagDecl->isConstexpr() &&
- S.checkingPotentialConstantExpression())
- return false;
+ // Silently reject constructors of invalid classes. The invalid class
+ // has been rejected elsewhere before.
+ if (CD && CD->getParent()->isInvalidDecl())
+ return false;
- // If the declaration is defined, declared 'constexpr' _and_ has a body,
- // the below diagnostic doesn't add anything useful.
- if (DiagDecl->isDefined() && DiagDecl->isConstexpr() &&
- DiagDecl->hasBody())
- return false;
+ // FIXME: If DiagDecl is an implicitly-declared special member function
+ // or an inheriting constructor, we should be much more explicit about why
+ // it's not constexpr.
+ if (CD && CD->isInheritingConstructor()) {
+ S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_invalid_inhctor,
+ 1)
+ << CD->getInheritedConstructor().getConstructor()->getParent();
+ S.Note(DiagDecl->getLocation(), diag::note_declared_at);
+ } else {
+ // Don't emit anything if the function isn't defined and we're checking
+ // for a constant expression. It might be defined at the point we're
+ // actually calling it.
+ bool IsExtern = DiagDecl->getStorageClass() == SC_Extern;
+ bool IsDefined = F->isDefined();
+ if (!IsDefined && !IsExtern && DiagDecl->isConstexpr() &&
+ S.checkingPotentialConstantExpression())
+ return false;
- S.FFDiag(S.Current->getLocation(OpPC),
- diag::note_constexpr_invalid_function, 1)
- << DiagDecl->isConstexpr() << (bool)CD << DiagDecl;
+ // If the declaration is defined, declared 'constexpr' _and_ has a body,
+ // the below diagnostic doesn't add anything useful.
+ if (DiagDecl->isDefined() && DiagDecl->isConstexpr() && DiagDecl->hasBody())
+ return false;
- if (DiagDecl->getDefinition())
- S.Note(DiagDecl->getDefinition()->getLocation(),
- diag::note_declared_at);
- else
- S.Note(DiagDecl->getLocation(), diag::note_declared_at);
- }
- } else {
S.FFDiag(S.Current->getLocation(OpPC),
- diag::note_invalid_subexpr_in_const_expr);
+ diag::note_constexpr_invalid_function, 1)
+ << DiagDecl->isConstexpr() << (bool)CD << DiagDecl;
+
+ if (DiagDecl->getDefinition())
+ S.Note(DiagDecl->getDefinition()->getLocation(), diag::note_declared_at);
+ else
+ S.Note(DiagDecl->getLocation(), diag::note_declared_at);
}
return false;
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 89f6fbe..5ab9c8e 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -75,7 +75,8 @@ bool CheckGlobalLoad(InterpState &S, CodePtr OpPC, const Block *B);
bool CheckLocalLoad(InterpState &S, CodePtr OpPC, const Block *B);
/// Checks if a value can be stored in a block.
-bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
+bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
+ bool WillBeActivated = false);
/// Checks if a value can be initialized.
bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
@@ -1977,13 +1978,12 @@ bool StoreActivate(InterpState &S, CodePtr OpPC) {
const T &Value = S.Stk.pop<T>();
const Pointer &Ptr = S.Stk.peek<Pointer>();
+ if (!CheckStore(S, OpPC, Ptr, /*WilLBeActivated=*/true))
+ return false;
if (Ptr.canBeInitialized()) {
Ptr.initialize();
Ptr.activate();
}
-
- if (!CheckStore(S, OpPC, Ptr))
- return false;
Ptr.deref<T>() = Value;
return true;
}
@@ -1993,12 +1993,12 @@ bool StoreActivatePop(InterpState &S, CodePtr OpPC) {
const T &Value = S.Stk.pop<T>();
const Pointer &Ptr = S.Stk.pop<Pointer>();
+ if (!CheckStore(S, OpPC, Ptr, /*WilLBeActivated=*/true))
+ return false;
if (Ptr.canBeInitialized()) {
Ptr.initialize();
Ptr.activate();
}
- if (!CheckStore(S, OpPC, Ptr))
- return false;
Ptr.deref<T>() = Value;
return true;
}
@@ -2007,7 +2007,8 @@ template <PrimType Name, class T = typename PrimConv<Name>::T>
bool StoreBitField(InterpState &S, CodePtr OpPC) {
const T &Value = S.Stk.pop<T>();
const Pointer &Ptr = S.Stk.peek<Pointer>();
- if (!CheckStore(S, OpPC, Ptr))
+
+ if (!CheckStore(S, OpPC, Ptr, /*WilLBeActivated=*/true))
return false;
if (Ptr.canBeInitialized())
Ptr.initialize();
@@ -2037,12 +2038,13 @@ template <PrimType Name, class T = typename PrimConv<Name>::T>
bool StoreBitFieldActivate(InterpState &S, CodePtr OpPC) {
const T &Value = S.Stk.pop<T>();
const Pointer &Ptr = S.Stk.peek<Pointer>();
+
+ if (!CheckStore(S, OpPC, Ptr, /*WilLBeActivated=*/true))
+ return false;
if (Ptr.canBeInitialized()) {
Ptr.initialize();
Ptr.activate();
}
- if (!CheckStore(S, OpPC, Ptr))
- return false;
if (const auto *FD = Ptr.getField())
Ptr.deref<T>() = Value.truncate(FD->getBitWidthValue());
else
@@ -2055,12 +2057,12 @@ bool StoreBitFieldActivatePop(InterpState &S, CodePtr OpPC) {
const T &Value = S.Stk.pop<T>();
const Pointer &Ptr = S.Stk.pop<Pointer>();
+ if (!CheckStore(S, OpPC, Ptr, /*WillBeActivated=*/true))
+ return false;
if (Ptr.canBeInitialized()) {
Ptr.initialize();
Ptr.activate();
}
- if (!CheckStore(S, OpPC, Ptr))
- return false;
if (const auto *FD = Ptr.getField())
Ptr.deref<T>() = Value.truncate(FD->getBitWidthValue());
else
@@ -2281,7 +2283,7 @@ std::optional<Pointer> OffsetHelper(InterpState &S, CodePtr OpPC,
}
}
- if (Invalid && S.getLangOpts().CPlusPlus)
+ if (Invalid && (S.getLangOpts().CPlusPlus || Ptr.inArray()))
return std::nullopt;
// Offset is valid - compute it on unsigned.
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index 839e84f..8f23001 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -749,7 +749,7 @@ static bool interp__builtin_overflowop(InterpState &S, CodePtr OpPC,
const CallExpr *Call,
unsigned BuiltinOp) {
const Pointer &ResultPtr = S.Stk.pop<Pointer>();
- if (ResultPtr.isDummy())
+ if (ResultPtr.isDummy() || !ResultPtr.isBlockPointer())
return false;
PrimType RHST = *S.getContext().classify(Call->getArg(1)->getType());
diff --git a/clang/lib/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.cpp b/clang/lib/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.cpp
index 90551c2..b42bfa3 100644
--- a/clang/lib/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.cpp
+++ b/clang/lib/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.cpp
@@ -177,6 +177,41 @@ static auto isPointerComparisonOperatorCall(std::string operator_name) {
pointee(anyOf(statusOrType(), statusType())))))));
}
+// The nullPointerConstant in the two matchers below is to support
+// absl::StatusOr<void*> X = nullptr.
+// nullptr does not match the bound type.
+// TODO: be less restrictive around convertible types in general.
+static auto isStatusOrValueAssignmentCall() {
+ using namespace ::clang::ast_matchers; // NOLINT: Too many names
+ return cxxOperatorCallExpr(
+ hasOverloadedOperatorName("="),
+ callee(cxxMethodDecl(ofClass(statusOrClass()))),
+ hasArgument(1, anyOf(hasType(hasUnqualifiedDesugaredType(
+ type(equalsBoundNode("T")))),
+ nullPointerConstant())));
+}
+
+static auto isStatusOrValueConstructor() {
+ using namespace ::clang::ast_matchers; // NOLINT: Too many names
+ return cxxConstructExpr(
+ hasType(statusOrType()),
+ hasArgument(0,
+ anyOf(hasType(hasCanonicalType(type(equalsBoundNode("T")))),
+ nullPointerConstant(),
+ hasType(namedDecl(hasAnyName("absl::in_place_t",
+ "std::in_place_t"))))));
+}
+
+static auto isStatusOrConstructor() {
+ using namespace ::clang::ast_matchers; // NOLINT: Too many names
+ return cxxConstructExpr(hasType(statusOrType()));
+}
+
+static auto isStatusConstructor() {
+ using namespace ::clang::ast_matchers; // NOLINT: Too many names
+ return cxxConstructExpr(hasType(statusType()));
+}
+
static auto
buildDiagnoseMatchSwitch(const UncheckedStatusOrAccessModelOptions &Options) {
return CFGMatchSwitchBuilder<const Environment,
@@ -528,6 +563,46 @@ static void transferEmplaceCall(const CXXMemberCallExpr *Expr,
State.Env.assume(OkVal.formula());
}
+static void transferValueAssignmentCall(const CXXOperatorCallExpr *Expr,
+ const MatchFinder::MatchResult &,
+ LatticeTransferState &State) {
+ assert(Expr->getNumArgs() > 1);
+
+ auto *StatusOrLoc = State.Env.get<RecordStorageLocation>(*Expr->getArg(0));
+ if (StatusOrLoc == nullptr)
+ return;
+
+ auto &OkVal = initializeStatusOr(*StatusOrLoc, State.Env);
+ State.Env.assume(OkVal.formula());
+}
+
+static void transferValueConstructor(const CXXConstructExpr *Expr,
+ const MatchFinder::MatchResult &,
+ LatticeTransferState &State) {
+ auto &OkVal =
+ initializeStatusOr(State.Env.getResultObjectLocation(*Expr), State.Env);
+ State.Env.assume(OkVal.formula());
+}
+
+static void transferStatusOrConstructor(const CXXConstructExpr *Expr,
+ const MatchFinder::MatchResult &,
+ LatticeTransferState &State) {
+ RecordStorageLocation &StatusOrLoc = State.Env.getResultObjectLocation(*Expr);
+ RecordStorageLocation &StatusLoc = locForStatus(StatusOrLoc);
+
+ if (State.Env.getValue(locForOk(StatusLoc)) == nullptr)
+ initializeStatusOr(StatusOrLoc, State.Env);
+}
+
+static void transferStatusConstructor(const CXXConstructExpr *Expr,
+ const MatchFinder::MatchResult &,
+ LatticeTransferState &State) {
+ RecordStorageLocation &StatusLoc = State.Env.getResultObjectLocation(*Expr);
+
+ if (State.Env.getValue(locForOk(StatusLoc)) == nullptr)
+ initializeStatus(StatusLoc, State.Env);
+}
+
CFGMatchSwitch<LatticeTransferState>
buildTransferMatchSwitch(ASTContext &Ctx,
CFGMatchSwitchBuilder<LatticeTransferState> Builder) {
@@ -573,6 +648,20 @@ buildTransferMatchSwitch(ASTContext &Ctx,
.CaseOfCFGStmt<CallExpr>(isNotOkStatusCall(), transferNotOkStatusCall)
.CaseOfCFGStmt<CXXMemberCallExpr>(isStatusOrMemberCallWithName("emplace"),
transferEmplaceCall)
+ .CaseOfCFGStmt<CXXOperatorCallExpr>(isStatusOrValueAssignmentCall(),
+ transferValueAssignmentCall)
+ .CaseOfCFGStmt<CXXConstructExpr>(isStatusOrValueConstructor(),
+ transferValueConstructor)
+ // N.B. These need to come after all other CXXConstructExpr.
+ // These are there to make sure that every Status and StatusOr object
+ // have their ok boolean initialized when constructed. If we were to
+ // lazily initialize them when we first access them, we can produce
+ // false positives if that first access is in a control flow statement.
+ // You can comment out these two constructors and see tests fail.
+ .CaseOfCFGStmt<CXXConstructExpr>(isStatusOrConstructor(),
+ transferStatusOrConstructor)
+ .CaseOfCFGStmt<CXXConstructExpr>(isStatusConstructor(),
+ transferStatusConstructor)
.Build();
}
diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index 468c930..aefc262 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -713,14 +713,16 @@ static void addSanitizers(const Triple &TargetTriple,
ThinOrFullLTOPhase) {
if (CodeGenOpts.hasSanitizeCoverage()) {
auto SancovOpts = getSancovOptsFromCGOpts(CodeGenOpts);
- MPM.addPass(SanitizerCoveragePass(
- SancovOpts, CodeGenOpts.SanitizeCoverageAllowlistFiles,
- CodeGenOpts.SanitizeCoverageIgnorelistFiles));
+ MPM.addPass(
+ SanitizerCoveragePass(SancovOpts, PB.getVirtualFileSystemPtr(),
+ CodeGenOpts.SanitizeCoverageAllowlistFiles,
+ CodeGenOpts.SanitizeCoverageIgnorelistFiles));
}
if (CodeGenOpts.hasSanitizeBinaryMetadata()) {
MPM.addPass(SanitizerBinaryMetadataPass(
getSanitizerBinaryMetadataOptions(CodeGenOpts),
+ PB.getVirtualFileSystemPtr(),
CodeGenOpts.SanitizeMetadataIgnorelistFiles));
}
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
index a56fa41..88bce18 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -945,6 +945,13 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
assert(false && "Unexpected action class for Flang tool.");
}
+ // We support some options that are invalid for Fortran and have no effect.
+ // These are solely for compatibility with other compilers. Emit a warning if
+ // any such options are provided, then proceed normally.
+ for (options::ID Opt : {options::OPT_fbuiltin, options::OPT_fno_builtin})
+ if (const Arg *A = Args.getLastArg(Opt))
+ D.Diag(diag::warn_drv_invalid_argument_for_flang) << A->getSpelling();
+
const InputInfo &Input = Inputs[0];
types::ID InputType = Input.getType();
diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp
index 65fc65e..f24b8ab 100644
--- a/clang/lib/Format/WhitespaceManager.cpp
+++ b/clang/lib/Format/WhitespaceManager.cpp
@@ -288,6 +288,9 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End,
ArrayRef<unsigned> Matches,
SmallVector<WhitespaceManager::Change, 16> &Changes) {
int Shift = 0;
+ // Set when the shift is applied anywhere in the line. Cleared when the line
+ // ends.
+ bool LineShifted = false;
// ScopeStack keeps track of the current scope depth. It contains the levels
// of at most 2 scopes. The first one is the one that the matched token is
@@ -339,8 +342,11 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End,
Changes[i - 1].Tok->is(tok::string_literal);
bool SkipMatchCheck = InsideNestedScope || ContinuedStringLiteral;
- if (CurrentChange.NewlinesBefore > 0 && !SkipMatchCheck)
- Shift = 0;
+ if (CurrentChange.NewlinesBefore > 0) {
+ LineShifted = false;
+ if (!SkipMatchCheck)
+ Shift = 0;
+ }
// If this is the first matching token to be aligned, remember by how many
// spaces it has to be shifted, so the rest of the changes on the line are
@@ -349,7 +355,6 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End,
Shift = Column - (RightJustify ? CurrentChange.TokenLength : 0) -
CurrentChange.StartOfTokenColumn;
ScopeStack = {CurrentChange.indentAndNestingLevel()};
- CurrentChange.Spaces += Shift;
}
if (Shift == 0)
@@ -358,8 +363,10 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End,
// This is for lines that are split across multiple lines, as mentioned in
// the ScopeStack comment. The stack size being 1 means that the token is
// not in a scope that should not move.
- if (ScopeStack.size() == 1u && CurrentChange.NewlinesBefore > 0 &&
- (ContinuedStringLiteral || InsideNestedScope)) {
+ if ((!Matches.empty() && Matches[0] == i) ||
+ (ScopeStack.size() == 1u && CurrentChange.NewlinesBefore > 0 &&
+ (ContinuedStringLiteral || InsideNestedScope))) {
+ LineShifted = true;
CurrentChange.Spaces += Shift;
}
@@ -369,9 +376,11 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End,
static_cast<int>(Changes[i].Tok->SpacesRequiredBefore) ||
CurrentChange.Tok->is(tok::eof));
- CurrentChange.StartOfTokenColumn += Shift;
- if (i + 1 != Changes.size())
- Changes[i + 1].PreviousEndOfTokenColumn += Shift;
+ if (LineShifted) {
+ CurrentChange.StartOfTokenColumn += Shift;
+ if (i + 1 != Changes.size())
+ Changes[i + 1].PreviousEndOfTokenColumn += Shift;
+ }
// If PointerAlignment is PAS_Right, keep *s or &s next to the token,
// except if the token is equal, then a space is needed.
diff --git a/clang/lib/Sema/SemaARM.cpp b/clang/lib/Sema/SemaARM.cpp
index 1c7c832d..ab37394 100644
--- a/clang/lib/Sema/SemaARM.cpp
+++ b/clang/lib/Sema/SemaARM.cpp
@@ -850,8 +850,10 @@ bool SemaARM::CheckARMBuiltinExclusiveCall(const TargetInfo &TI,
unsigned BuiltinID,
CallExpr *TheCall) {
assert((BuiltinID == ARM::BI__builtin_arm_ldrex ||
+ BuiltinID == ARM::BI__builtin_arm_ldrexd ||
BuiltinID == ARM::BI__builtin_arm_ldaex ||
BuiltinID == ARM::BI__builtin_arm_strex ||
+ BuiltinID == ARM::BI__builtin_arm_strexd ||
BuiltinID == ARM::BI__builtin_arm_stlex ||
BuiltinID == AArch64::BI__builtin_arm_ldrex ||
BuiltinID == AArch64::BI__builtin_arm_ldaex ||
@@ -859,9 +861,12 @@ bool SemaARM::CheckARMBuiltinExclusiveCall(const TargetInfo &TI,
BuiltinID == AArch64::BI__builtin_arm_stlex) &&
"unexpected ARM builtin");
bool IsLdrex = BuiltinID == ARM::BI__builtin_arm_ldrex ||
+ BuiltinID == ARM::BI__builtin_arm_ldrexd ||
BuiltinID == ARM::BI__builtin_arm_ldaex ||
BuiltinID == AArch64::BI__builtin_arm_ldrex ||
BuiltinID == AArch64::BI__builtin_arm_ldaex;
+ bool IsDoubleWord = BuiltinID == ARM::BI__builtin_arm_ldrexd ||
+ BuiltinID == ARM::BI__builtin_arm_strexd;
ASTContext &Context = getASTContext();
DeclRefExpr *DRE =
@@ -928,6 +933,11 @@ bool SemaARM::CheckARMBuiltinExclusiveCall(const TargetInfo &TI,
if (!TI.getTriple().isAArch64()) {
unsigned Mask = TI.getARMLDREXMask();
unsigned Bits = Context.getTypeSize(ValType);
+ if (IsDoubleWord) {
+ // Explicit request for ldrexd/strexd means only double word sizes
+ // supported if the target supports them.
+ Mask &= TargetInfo::ARM_LDREX_D;
+ }
bool Supported =
(llvm::isPowerOf2_64(Bits)) && Bits >= 8 && (Mask & (Bits / 8));
@@ -968,8 +978,11 @@ bool SemaARM::CheckARMBuiltinExclusiveCall(const TargetInfo &TI,
}
}
} else {
+ bool EmitDoubleWordDiagnostic =
+ IsDoubleWord && !Mask && TI.getARMLDREXMask();
Diag(DRE->getBeginLoc(),
diag::err_atomic_exclusive_builtin_pointer_size_none)
+ << (EmitDoubleWordDiagnostic ? 1 : 0)
<< PointerArg->getSourceRange();
}
}
@@ -1013,8 +1026,10 @@ bool SemaARM::CheckARMBuiltinFunctionCall(const TargetInfo &TI,
unsigned BuiltinID,
CallExpr *TheCall) {
if (BuiltinID == ARM::BI__builtin_arm_ldrex ||
+ BuiltinID == ARM::BI__builtin_arm_ldrexd ||
BuiltinID == ARM::BI__builtin_arm_ldaex ||
BuiltinID == ARM::BI__builtin_arm_strex ||
+ BuiltinID == ARM::BI__builtin_arm_strexd ||
BuiltinID == ARM::BI__builtin_arm_stlex) {
return CheckARMBuiltinExclusiveCall(TI, BuiltinID, TheCall);
}
diff --git a/clang/test/AST/ByteCode/builtin-functions.cpp b/clang/test/AST/ByteCode/builtin-functions.cpp
index d8572ba..e9093b2 100644
--- a/clang/test/AST/ByteCode/builtin-functions.cpp
+++ b/clang/test/AST/ByteCode/builtin-functions.cpp
@@ -1855,3 +1855,8 @@ namespace InitParam {
}
#endif
+
+namespace SAddOverflowInt {
+ int a;
+ void foo(void) { a *= __builtin_sadd_overflow(1, 2, 0); }
+}
diff --git a/clang/test/AST/ByteCode/c.c b/clang/test/AST/ByteCode/c.c
index cfdc9d0..3360d4f 100644
--- a/clang/test/AST/ByteCode/c.c
+++ b/clang/test/AST/ByteCode/c.c
@@ -381,3 +381,9 @@ static char foo_(a) // all-warning {{definition without a prototype}}
static void bar_(void) {
foo_(foo_(1));
}
+
+void foo2(void*);
+void bar2(void) {
+ int a[2][3][4][5]; // all-note {{array 'a' declared here}}
+ foo2(&a[0][4]); // all-warning {{array index 4 is past the end of the array}}
+}
diff --git a/clang/test/AST/ByteCode/records.cpp b/clang/test/AST/ByteCode/records.cpp
index 00218ba..83f32c9 100644
--- a/clang/test/AST/ByteCode/records.cpp
+++ b/clang/test/AST/ByteCode/records.cpp
@@ -1861,3 +1861,24 @@ namespace PrimitiveInitializedByInitList {
} c{ 17 };
static_assert(c.b == 17, "");
}
+
+namespace MethodWillHaveBody {
+ class A {
+ public:
+ static constexpr int get_value2() { return 1 + get_value(); }
+ static constexpr int get_value() { return 1; }
+ };
+ static_assert(A::get_value2() == 2, "");
+
+ template<typename T> constexpr T f(T);
+ template<typename T> constexpr T g(T t) {
+ typedef int arr[f(T())]; // both-warning {{variable length array}} \
+ // both-note {{undefined function 'f<int>'}}
+ return t;
+ }
+ template<typename T> constexpr T f(T t) { // both-note {{declared here}}
+ typedef int arr[g(T())]; // both-note {{instantiation of}}
+ return t;
+ }
+ int n = f(0); // both-note {{instantiation of}}
+}
diff --git a/clang/test/AST/ByteCode/unions.cpp b/clang/test/AST/ByteCode/unions.cpp
index 6bccbda..4140704 100644
--- a/clang/test/AST/ByteCode/unions.cpp
+++ b/clang/test/AST/ByteCode/unions.cpp
@@ -977,4 +977,13 @@ namespace UnionMemberOnePastEnd {
}
static_assert(!b());
}
+
+namespace ActicvateInvalidPtr {
+ constexpr void bar() { // both-error {{never produces a constant expression}}
+ union {
+ int a[1];
+ } foo;
+ foo.a[1] = 0; // both-note {{assignment to dereferenced one-past-the-end pointer}}
+ }
+}
#endif
diff --git a/clang/test/CodeGen/builtins-arm-exclusive.c b/clang/test/CodeGen/builtins-arm-exclusive.c
index d2aaf26..f27dcfc 100644
--- a/clang/test/CodeGen/builtins-arm-exclusive.c
+++ b/clang/test/CodeGen/builtins-arm-exclusive.c
@@ -312,3 +312,49 @@ int test_stlex_128(__int128 *addr, __int128 val) {
}
#endif
+
+#ifdef __arm__
+// ARM exclusive atomic builtins
+
+int test_ldrexd(char *addr, long long *addr64, float *addrfloat) {
+// CHECK-LABEL: @test_ldrexd
+ int sum = 0;
+ sum += __builtin_arm_ldrexd((long long *)addr);
+// CHECK: call { i32, i32 } @llvm.arm.ldrexd(ptr %addr)
+
+ sum += __builtin_arm_ldrexd(addr64);
+// CHECK: call { i32, i32 } @llvm.arm.ldrexd(ptr %addr64)
+
+ sum += __builtin_arm_ldrexd((double *)addr);
+// CHECK: [[STRUCTRES:%.*]] = call { i32, i32 } @llvm.arm.ldrexd(ptr %addr)
+// CHECK: [[RESHI:%.*]] = extractvalue { i32, i32 } [[STRUCTRES]], 1
+// CHECK: [[RESLO:%.*]] = extractvalue { i32, i32 } [[STRUCTRES]], 0
+// CHECK: [[RESHI64:%.*]] = zext i32 [[RESHI]] to i64
+// CHECK: [[RESLO64:%.*]] = zext i32 [[RESLO]] to i64
+// CHECK: [[RESHIHI:%.*]] = shl nuw i64 [[RESHI64]], 32
+// CHECK: [[INTRES:%.*]] = or i64 [[RESHIHI]], [[RESLO64]]
+
+ return sum;
+}
+
+int test_strexd(char *addr) {
+// CHECK-LABEL: @test_strexd
+ int res = 0;
+ res |= __builtin_arm_strexd(42, (long long *)addr);
+// CHECK: store i64 42, ptr [[TMP:%.*]], align 8
+// CHECK: [[LOHI:%.*]] = load { i32, i32 }, ptr [[TMP]]
+// CHECK: [[LO:%.*]] = extractvalue { i32, i32 } [[LOHI]], 0
+// CHECK: [[HI:%.*]] = extractvalue { i32, i32 } [[LOHI]], 1
+// CHECK: call i32 @llvm.arm.strexd(i32 [[LO]], i32 [[HI]], ptr %addr)
+
+ res |= __builtin_arm_strexd(3.14159, (double *)addr);
+// CHECK: store double 3.141590e+00, ptr [[TMP:%.*]], align 8
+// CHECK: [[LOHI:%.*]] = load { i32, i32 }, ptr [[TMP]]
+// CHECK: [[LO:%.*]] = extractvalue { i32, i32 } [[LOHI]], 0
+// CHECK: [[HI:%.*]] = extractvalue { i32, i32 } [[LOHI]], 1
+// CHECK: call i32 @llvm.arm.strexd(i32 [[LO]], i32 [[HI]], ptr %addr)
+
+ return res;
+}
+
+#endif
diff --git a/clang/test/CodeGenCXX/builtins-arm-exclusive.cpp b/clang/test/CodeGenCXX/builtins-arm-exclusive.cpp
index d30631f..ca27193 100644
--- a/clang/test/CodeGenCXX/builtins-arm-exclusive.cpp
+++ b/clang/test/CodeGenCXX/builtins-arm-exclusive.cpp
@@ -22,3 +22,35 @@ void test_ldrex() {
void tset_strex() {
__builtin_arm_strex(true, &b);
}
+
+#ifdef __arm__
+// ARM exclusive atomic builtins
+
+long long c;
+
+// CHECK-LABEL: @_Z11test_ldrexdv()
+// CHECK: [[STRUCTRES:%.*]] = call { i32, i32 } @llvm.arm.ldrexd(ptr @c)
+// CHECK: [[RESHI:%.*]] = extractvalue { i32, i32 } [[STRUCTRES]], 1
+// CHECK: [[RESLO:%.*]] = extractvalue { i32, i32 } [[STRUCTRES]], 0
+// CHECK: [[RESHI64:%.*]] = zext i32 [[RESHI]] to i64
+// CHECK: [[RESLO64:%.*]] = zext i32 [[RESLO]] to i64
+// CHECK: [[RESHIHI:%.*]] = shl nuw i64 [[RESHI64]], 32
+// CHECK: [[INTRES:%.*]] = or i64 [[RESHIHI]], [[RESLO64]]
+// CHECK: store i64 [[INTRES]], ptr @c, align 8
+
+void test_ldrexd() {
+ c = __builtin_arm_ldrexd(&c);
+}
+
+// CHECK-LABEL: @_Z11tset_strexdv()
+// CHECK: store i64 42, ptr [[TMP:%.*]], align 8
+// CHECK: [[LOHI:%.*]] = load { i32, i32 }, ptr [[TMP]]
+// CHECK: [[LO:%.*]] = extractvalue { i32, i32 } [[LOHI]], 0
+// CHECK: [[HI:%.*]] = extractvalue { i32, i32 } [[LOHI]], 1
+// CHECK: %{{.*}} = call i32 @llvm.arm.strexd(i32 [[LO]], i32 [[HI]], ptr @c)
+
+void tset_strexd() {
+ __builtin_arm_strexd(42, &c);
+}
+
+#endif
diff --git a/clang/test/DebugInfo/ObjC/property-2.m b/clang/test/DebugInfo/ObjC/property-2.m
deleted file mode 100644
index f152131..0000000
--- a/clang/test/DebugInfo/ObjC/property-2.m
+++ /dev/null
@@ -1,18 +0,0 @@
-// FIXME: Check IR rather than asm, then triple is not needed.
-// RUN: %clang_cc1 -triple %itanium_abi_triple -S -debug-info-kind=limited -x objective-c < %s | grep DW_AT_name
-@interface Foo {
- int i;
-}
-@property int i;
-@end
-
-@implementation Foo
-@synthesize i;
-@end
-
-int bar(Foo *f) {
- int i = 1;
- f.i = 2;
- i = f.i;
- return i;
-}
diff --git a/clang/test/DebugInfo/ObjC/property-auto-synth.m b/clang/test/DebugInfo/ObjC/property-auto-synth.m
new file mode 100644
index 0000000..5e961d4
--- /dev/null
+++ b/clang/test/DebugInfo/ObjC/property-auto-synth.m
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s
+
+// CHECK-NOT: setter
+// CHECK-NOT: getter
+
+@interface I1
+@property int p1;
+@end
+
+@implementation I1
+@end
+
+void foo(I1 *ptr) {}
diff --git a/clang/test/DebugInfo/ObjC/property-basic.m b/clang/test/DebugInfo/ObjC/property-basic.m
new file mode 100644
index 0000000..65e1d7a
--- /dev/null
+++ b/clang/test/DebugInfo/ObjC/property-basic.m
@@ -0,0 +1,20 @@
+// Checks basic debug-info generation for property. Makes sure we
+// create a DIObjCProperty for the synthesized property.
+
+// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s
+
+// CHECK: !DIObjCProperty(name: "p1"
+// CHECK-SAME: attributes: 2316
+// CHECK-SAME: type: ![[P1_TYPE:[0-9]+]]
+//
+// CHECK: ![[P1_TYPE]] = !DIBasicType(name: "int"
+
+@interface I1 {
+int p1;
+}
+@property int p1;
+@end
+
+@implementation I1
+@synthesize p1;
+@end
diff --git a/clang/test/DebugInfo/ObjC/property-explicit-accessors.m b/clang/test/DebugInfo/ObjC/property-explicit-accessors.m
new file mode 100644
index 0000000..86eade6
--- /dev/null
+++ b/clang/test/DebugInfo/ObjC/property-explicit-accessors.m
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s
+
+// CHECK: !DIObjCProperty(name: "baseInt"
+// CHECK-SAME: setter: "mySetBaseInt:"
+// CHECK-SAME: getter: "myGetBaseInt"
+// CHECK-SAME: attributes: 2446
+// CHECK-SAME: type: ![[P1_TYPE:[0-9]+]]
+//
+// CHECK: ![[P1_TYPE]] = !DIBasicType(name: "int"
+
+@interface BaseClass2
+{
+ int _baseInt;
+}
+- (int) myGetBaseInt;
+- (void) mySetBaseInt: (int) in_int;
+@property(getter=myGetBaseInt,setter=mySetBaseInt:) int baseInt;
+@end
+
+@implementation BaseClass2
+
+- (int) myGetBaseInt
+{
+ return _baseInt;
+}
+
+- (void) mySetBaseInt: (int) in_int
+{
+ _baseInt = 2 * in_int;
+}
+@end
+
+
+void foo(BaseClass2 *ptr) {}
diff --git a/clang/test/DebugInfo/ObjC/property-explicit-ivar.m b/clang/test/DebugInfo/ObjC/property-explicit-ivar.m
new file mode 100644
index 0000000..5092e23
--- /dev/null
+++ b/clang/test/DebugInfo/ObjC/property-explicit-ivar.m
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s
+
+// CHECK: ![[BASE_PROP:[0-9]+]] = !DIObjCProperty(name: "base"
+// CHECK-SAME: attributes: 2316
+// CHECK-SAME: type: ![[P1_TYPE:[0-9]+]]
+//
+// CHECK: ![[P1_TYPE]] = !DIBasicType(name: "int"
+//
+// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "_customIvar"
+// CHECK-SAME: extraData: ![[BASE_PROP]]
+
+@interface C {
+ int _customIvar;
+}
+@property int base;
+@end
+
+@implementation C
+@synthesize base = _customIvar;
+@end
+
+void foo(C *cptr) {}
diff --git a/clang/test/DebugInfo/ObjC/property.m b/clang/test/DebugInfo/ObjC/property.m
deleted file mode 100644
index ca013b2..0000000
--- a/clang/test/DebugInfo/ObjC/property.m
+++ /dev/null
@@ -1,15 +0,0 @@
-// FIXME: Check IR rather than asm, then triple is not needed.
-// RUN: %clang_cc1 -triple %itanium_abi_triple -S -debug-info-kind=limited %s -o - | FileCheck %s
-
-// CHECK: AT_APPLE_property_name
-// CHECK: AT_APPLE_property_attribute
-// CHECK: AT_APPLE_property
-@interface I1 {
-int p1;
-}
-@property int p1;
-@end
-
-@implementation I1
-@synthesize p1;
-@end
diff --git a/clang/test/DebugInfo/ObjC/property2.m b/clang/test/DebugInfo/ObjC/property2.m
deleted file mode 100644
index 7e0a5e9..0000000
--- a/clang/test/DebugInfo/ObjC/property2.m
+++ /dev/null
@@ -1,15 +0,0 @@
-// FIXME: Check IR rather than asm, then triple is not needed.
-// RUN: %clang_cc1 -triple %itanium_abi_triple -S -debug-info-kind=limited %s -o - | FileCheck %s
-
-// CHECK: AT_APPLE_property_name
-@interface C {
- int _base;
-}
-@property int base;
-@end
-
-@implementation C
-@synthesize base = _base;
-@end
-
-void foo(C *cptr) {}
diff --git a/clang/test/DebugInfo/ObjC/property4.m b/clang/test/DebugInfo/ObjC/property4.m
deleted file mode 100644
index 1f489f2..0000000
--- a/clang/test/DebugInfo/ObjC/property4.m
+++ /dev/null
@@ -1,18 +0,0 @@
-// FIXME: Check IR rather than asm, then triple is not needed.
-// RUN: %clang_cc1 -triple %itanium_abi_triple -S -debug-info-kind=limited %s -o - | FileCheck %s
-
-// CHECK: AT_APPLE_property_name
-// CHECK-NOT: AT_APPLE_property_getter
-// CHECK-NOT: AT_APPLE_property_setter
-// CHECK: AT_APPLE_property_attribute
-// CHECK: AT_APPLE_property
-
-
-@interface I1
-@property int p1;
-@end
-
-@implementation I1
-@end
-
-void foo(I1 *ptr) {}
diff --git a/clang/test/DebugInfo/ObjC/property5.m b/clang/test/DebugInfo/ObjC/property5.m
deleted file mode 100644
index 8b70f1f..0000000
--- a/clang/test/DebugInfo/ObjC/property5.m
+++ /dev/null
@@ -1,33 +0,0 @@
-// FIXME: Check IR rather than asm, then triple is not needed.
-// RUN: %clang_cc1 -triple %itanium_abi_triple -S -debug-info-kind=limited %s -o - | FileCheck %s
-
-// CHECK: AT_APPLE_property_name
-// CHECK: AT_APPLE_property_getter
-// CHECK: AT_APPLE_property_setter
-// CHECK: AT_APPLE_property_attribute
-// CHECK: AT_APPLE_property
-
-@interface BaseClass2
-{
- int _baseInt;
-}
-- (int) myGetBaseInt;
-- (void) mySetBaseInt: (int) in_int;
-@property(getter=myGetBaseInt,setter=mySetBaseInt:) int baseInt;
-@end
-
-@implementation BaseClass2
-
-- (int) myGetBaseInt
-{
- return _baseInt;
-}
-
-- (void) mySetBaseInt: (int) in_int
-{
- _baseInt = 2 * in_int;
-}
-@end
-
-
-void foo(BaseClass2 *ptr) {}
diff --git a/clang/test/DebugInfo/ObjCXX/lit.local.cfg b/clang/test/DebugInfo/ObjCXX/lit.local.cfg
new file mode 100644
index 0000000..8d5c476
--- /dev/null
+++ b/clang/test/DebugInfo/ObjCXX/lit.local.cfg
@@ -0,0 +1,5 @@
+# objective-CXX is not supported on AIX and zOS
+unsupported_platforms = [ "system-aix", "system-zos" ]
+
+if any(up in config.available_features for up in unsupported_platforms):
+ config.unsupported = True
diff --git a/clang/test/Sema/builtins-arm-exclusive-124.c b/clang/test/Sema/builtins-arm-exclusive-124.c
index 013ae3f..b35ac18 100644
--- a/clang/test/Sema/builtins-arm-exclusive-124.c
+++ b/clang/test/Sema/builtins-arm-exclusive-124.c
@@ -24,3 +24,27 @@ int test_strex(char *addr) {
res |= __builtin_arm_strex(42, (long long *)addr); // expected-error {{address argument to load or store exclusive builtin must be a pointer to 1,2 or 4 byte type}}
return res;
}
+
+int test_ldrexd(char *addr) {
+ int sum = 0;
+ sum += __builtin_arm_ldrexd(addr); // expected-error {{eight-byte load and store exclusive builtins are not available on this architecture}}
+ sum += __builtin_arm_ldrexd((short *)addr); // expected-error {{eight-byte load and store exclusive builtins are not available on this architecture}}
+ sum += __builtin_arm_ldrexd((int *)addr); // expected-error {{eight-byte load and store exclusive builtins are not available on this architecture}}
+ sum += __builtin_arm_ldrexd((long long *)addr); // expected-error {{eight-byte load and store exclusive builtins are not available on this architecture}}
+ sum += __builtin_arm_ldrexd((unsigned long long *)addr); // expected-error {{eight-byte load and store exclusive builtins are not available on this architecture}}
+ sum += __builtin_arm_ldrexd((float *)addr); // expected-error {{eight-byte load and store exclusive builtins are not available on this architecture}}
+ sum += __builtin_arm_ldrexd((double *)addr); // expected-error {{eight-byte load and store exclusive builtins are not available on this architecture}}
+ return sum;
+}
+
+int test_strexd(char *addr) {
+ int res = 0;
+ res |= __builtin_arm_strexd(4, addr); // expected-error {{eight-byte load and store exclusive builtins are not available on this architecture}}
+ res |= __builtin_arm_strexd(42, (short *)addr); // expected-error {{eight-byte load and store exclusive builtins are not available on this architecture}}
+ res |= __builtin_arm_strexd(42, (int *)addr); // expected-error {{eight-byte load and store exclusive builtins are not available on this architecture}}
+ res |= __builtin_arm_strexd(42, (long long *)addr); // expected-error {{eight-byte load and store exclusive builtins are not available on this architecture}}
+ res |= __builtin_arm_strexd(42, (unsigned long long *)addr); // expected-error {{eight-byte load and store exclusive builtins are not available on this architecture}}
+ res |= __builtin_arm_strexd(2.71828f, (float *)addr); // expected-error {{eight-byte load and store exclusive builtins are not available on this architecture}}
+ res |= __builtin_arm_strexd(3.14159, (double *)addr); // expected-error {{eight-byte load and store exclusive builtins are not available on this architecture}}
+ return res;
+}
diff --git a/clang/test/Sema/builtins-arm-exclusive-4.c b/clang/test/Sema/builtins-arm-exclusive-4.c
index 68f01f5..0d31ce6 100644
--- a/clang/test/Sema/builtins-arm-exclusive-4.c
+++ b/clang/test/Sema/builtins-arm-exclusive-4.c
@@ -20,3 +20,21 @@ int test_strex(char *addr) {
res |= __builtin_arm_strex(42, (long long *)addr); // expected-error {{address argument to load or store exclusive builtin must be a pointer to 4 byte type}}
return res;
}
+
+int test_ldrexd(char *addr) {
+ int sum = 0;
+ sum += __builtin_arm_ldrexd(addr); // expected-error {{load and store exclusive builtins are not available on this architecture}}
+ sum += __builtin_arm_ldrexd((short *)addr); // expected-error {{load and store exclusive builtins are not available on this architecture}}
+ sum += __builtin_arm_ldrexd((int *)addr); // expected-error {{load and store exclusive builtins are not available on this architecture}}
+ sum += __builtin_arm_ldrexd((long long *)addr); // expected-error {{load and store exclusive builtins are not available on this architecture}}
+ return sum;
+}
+
+int test_strexd(char *addr) {
+ int res = 0;
+ res |= __builtin_arm_strexd(4, addr); // expected-error {{load and store exclusive builtins are not available on this architecture}}
+ res |= __builtin_arm_strexd(42, (short *)addr); // expected-error {{load and store exclusive builtins are not available on this architecture}}
+ res |= __builtin_arm_strexd(42, (int *)addr); // expected-error {{load and store exclusive builtins are not available on this architecture}}
+ res |= __builtin_arm_strexd(42, (long long *)addr); // expected-error {{load and store exclusive builtins are not available on this architecture}}
+ return res;
+}
diff --git a/clang/test/Sema/builtins-arm-exclusive-none.c b/clang/test/Sema/builtins-arm-exclusive-none.c
index 76d327f..2ef910d 100644
--- a/clang/test/Sema/builtins-arm-exclusive-none.c
+++ b/clang/test/Sema/builtins-arm-exclusive-none.c
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -triple armv6m -fsyntax-only -verify %s
// Armv6-M does not support exclusive loads/stores at all, so all uses of
-// __builtin_arm_ldrex and __builtin_arm_strex is forbidden.
+// __builtin_arm_ldrex[d] and __builtin_arm_strex[d] is forbidden.
int test_ldrex(char *addr) {
int sum = 0;
@@ -20,3 +20,21 @@ int test_strex(char *addr) {
res |= __builtin_arm_strex(42, (long long *)addr); // expected-error {{load and store exclusive builtins are not available on this architecture}}
return res;
}
+
+int test_ldrexd(char *addr) {
+ int sum = 0;
+ sum += __builtin_arm_ldrexd(addr); // expected-error {{load and store exclusive builtins are not available on this architecture}}
+ sum += __builtin_arm_ldrexd((short *)addr); // expected-error {{load and store exclusive builtins are not available on this architecture}}
+ sum += __builtin_arm_ldrexd((int *)addr); // expected-error {{load and store exclusive builtins are not available on this architecture}}
+ sum += __builtin_arm_ldrexd((long long *)addr); // expected-error {{load and store exclusive builtins are not available on this architecture}}
+ return sum;
+}
+
+int test_strexd(char *addr) {
+ int res = 0;
+ res |= __builtin_arm_strexd(4, addr); // expected-error {{load and store exclusive builtins are not available on this architecture}}
+ res |= __builtin_arm_strexd(42, (short *)addr); // expected-error {{load and store exclusive builtins are not available on this architecture}}
+ res |= __builtin_arm_strexd(42, (int *)addr); // expected-error {{load and store exclusive builtins are not available on this architecture}}
+ res |= __builtin_arm_strexd(42, (long long *)addr); // expected-error {{load and store exclusive builtins are not available on this architecture}}
+ return res;
+}
diff --git a/clang/test/Sema/builtins-arm-exclusive.c b/clang/test/Sema/builtins-arm-exclusive.c
index 49aea15..dbb3de5 100644
--- a/clang/test/Sema/builtins-arm-exclusive.c
+++ b/clang/test/Sema/builtins-arm-exclusive.c
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -triple armv7 -fsyntax-only -verify %s
-// General tests of __builtin_arm_ldrex and __builtin_arm_strex error checking.
+// General tests of __builtin_arm_ldrex[d] and __builtin_arm_strex[d] error checking.
//
// This test is compiled for Armv7-A, which provides exclusive load/store
// instructions for 1-, 2-, 4- and 8-byte quantities. Other Arm architecture
@@ -63,6 +63,57 @@ int test_strex(char *addr) {
return res;
}
+int test_ldrexd(char *addr) {
+ int sum = 0;
+ sum += __builtin_arm_ldrexd(addr); // expected-error {{address argument to load or store exclusive builtin must be a pointer to 8 byte type}}
+ sum += __builtin_arm_ldrexd((short *)addr); // expected-error {{address argument to load or store exclusive builtin must be a pointer to 8 byte type}}
+ sum += __builtin_arm_ldrexd((int *)addr); // expected-error {{address argument to load or store exclusive builtin must be a pointer to 8 byte type}}
+ sum += __builtin_arm_ldrexd((long long *)addr);
+ sum += __builtin_arm_ldrexd((float *)addr); // expected-error {{address argument to load or store exclusive builtin must be a pointer to 8 byte type}}
+ sum += __builtin_arm_ldrexd((double *)addr);
+ sum += *__builtin_arm_ldrexd((int **)addr); // expected-error {{address argument to load or store exclusive builtin must be a pointer to 8 byte type}}
+ sum += __builtin_arm_ldrexd((struct Simple **)addr)->a; // expected-error {{address argument to load or store exclusive builtin must be a pointer to 8 byte type}}
+ sum += __builtin_arm_ldrexd((volatile char *)addr); // expected-error {{address argument to load or store exclusive builtin must be a pointer to 8 byte type}}
+ sum += __builtin_arm_ldrexd((const volatile char *)addr); // expected-error {{address argument to load or store exclusive builtin must be a pointer to 8 byte type}}
+
+ // In principle this might be valid, but stick to ints and floats for scalar
+ // types at the moment.
+ sum += __builtin_arm_ldrexd((struct Simple *)addr).a; // expected-error {{address argument to atomic builtin must be a pointer to}}
+
+ sum += __builtin_arm_ldrexd((__int128 *)addr); // expected-error {{__int128 is not supported on this target}} expected-error {{address argument to load or store exclusive builtin must be a pointer to 8 byte type}}
+
+ __builtin_arm_ldrexd(); // expected-error {{too few arguments to function call}}
+ __builtin_arm_ldrexd(1, 2); // expected-error {{too many arguments to function call}}
+ return sum;
+}
+
+int test_strexd(char *addr) {
+ int res = 0;
+ struct Simple var = {0};
+ res |= __builtin_arm_strexd(4, addr); // expected-error {{address argument to load or store exclusive builtin must be a pointer to 8 byte type}}
+ res |= __builtin_arm_strexd(42, (short *)addr); // expected-error {{address argument to load or store exclusive builtin must be a pointer to 8 byte type}}
+ res |= __builtin_arm_strexd(42, (int *)addr); // expected-error {{address argument to load or store exclusive builtin must be a pointer to 8 byte type}}
+ res |= __builtin_arm_strexd(42, (long long *)addr);
+ res |= __builtin_arm_strexd(2.71828f, (float *)addr); // expected-error {{address argument to load or store exclusive builtin must be a pointer to 8 byte type}}
+ res |= __builtin_arm_strexd(3.14159, (double *)addr);
+ res |= __builtin_arm_strexd(&var, (struct Simple **)addr); // expected-error {{address argument to load or store exclusive builtin must be a pointer to 8 byte type}}
+
+ res |= __builtin_arm_strexd(42, (volatile char *)addr); // expected-error {{address argument to load or store exclusive builtin must be a pointer to 8 byte type}}
+ res |= __builtin_arm_strexd(42, (char *const)addr); // expected-error {{address argument to load or store exclusive builtin must be a pointer to 8 byte type}}
+ res |= __builtin_arm_strexd(42, (const char *)addr); // expected-warning {{passing 'const char *' to parameter of type 'volatile char *' discards qualifiers}} expected-error {{address argument to load or store exclusive builtin must be a pointer to 8 byte type}}
+
+
+ res |= __builtin_arm_strexd(var, (struct Simple *)addr); // expected-error {{address argument to atomic builtin must be a pointer to}}
+ res |= __builtin_arm_strexd(var, (struct Simple **)addr); // expected-error {{passing 'struct Simple' to parameter of incompatible type 'struct Simple *'}} expected-error {{address argument to load or store exclusive builtin must be a pointer to 8 byte type}}
+ res |= __builtin_arm_strexd(&var, (struct Simple **)addr).a; // expected-error {{is not a structure or union}} expected-error {{address argument to load or store exclusive builtin must be a pointer to 8 byte type}}
+
+ res |= __builtin_arm_strexd(1, (__int128 *)addr); // expected-error {{__int128 is not supported on this target}} expected-error {{address argument to load or store exclusive builtin must be a pointer to 8 byte type}}
+
+ __builtin_arm_strexd(1); // expected-error {{too few arguments to function call}}
+ __builtin_arm_strexd(1, 2, 3); // expected-error {{too many arguments to function call}}
+ return res;
+}
+
int test_ldaex(char *addr) {
int sum = 0;
sum += __builtin_arm_ldaex(addr);
diff --git a/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp b/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp
index 425beb9..5635ff4 100644
--- a/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp
@@ -2975,6 +2975,217 @@ TEST_P(UncheckedStatusOrAccessModelTest, Emplace) {
)cc");
}
+TEST_P(UncheckedStatusOrAccessModelTest, ValueConstruction) {
+ ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_access_test_defs.h"
+
+ void target() {
+ STATUSOR_BOOL result = false;
+ result.value();
+ }
+ )cc");
+ ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_access_test_defs.h"
+
+ void target() {
+ STATUSOR_INT result = 21;
+ result.value();
+ }
+ )cc");
+ ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_access_test_defs.h"
+
+ void target() {
+ STATUSOR_INT result = Make<STATUSOR_INT>();
+ result.value(); // [[unsafe]]
+ }
+ )cc");
+ ExpectDiagnosticsFor(
+ R"cc(
+#include "unchecked_statusor_access_test_defs.h"
+
+ void target() {
+ STATUSOR_BOOL result = false;
+ if (result.ok())
+ result.value();
+ else
+ result.value();
+ }
+ )cc");
+
+ ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_access_test_defs.h"
+
+ void target() {
+ STATUSOR_BOOL result(false);
+ result.value();
+ }
+ )cc");
+ ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_access_test_defs.h"
+
+ void target() {
+ STATUSOR_INT result(21);
+ result.value();
+ }
+ )cc");
+ ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_access_test_defs.h"
+
+ void target() {
+ STATUSOR_INT result(Make<STATUSOR_INT>());
+ result.value(); // [[unsafe]]
+ }
+ )cc");
+ ExpectDiagnosticsFor(
+ R"cc(
+#include "unchecked_statusor_access_test_defs.h"
+
+ void target() {
+ STATUSOR_BOOL result(false);
+ if (result.ok())
+ result.value();
+ else
+ result.value();
+ }
+ )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, ValueAssignment) {
+ ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_access_test_defs.h"
+
+ void target() {
+ STATUSOR_BOOL result;
+ result = false;
+ result.value();
+ }
+ )cc");
+ ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_access_test_defs.h"
+
+ void target() {
+ STATUSOR_INT result;
+ result = 21;
+ result.value();
+ }
+ )cc");
+ ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_access_test_defs.h"
+
+ void target() {
+ STATUSOR_INT result;
+ result = Make<STATUSOR_INT>();
+ result.value(); // [[unsafe]]
+ }
+ )cc");
+ ExpectDiagnosticsFor(
+ R"cc(
+#include "unchecked_statusor_access_test_defs.h"
+
+ void target() {
+ STATUSOR_BOOL result;
+ result = false;
+ if (result.ok())
+ result.value();
+ else
+ result.value();
+ }
+ )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, NestedStatusOr) {
+ ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_access_test_defs.h"
+
+ void target() {
+ absl::StatusOr<STATUSOR_INT> result;
+ result = Make<STATUSOR_INT>();
+ result.value();
+ }
+ )cc");
+ ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_access_test_defs.h"
+
+ void target() {
+ absl::StatusOr<STATUSOR_INT> result = Make<STATUSOR_INT>();
+ result.value();
+ }
+ )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, PtrConstruct) {
+ ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_access_test_defs.h"
+
+ void target() {
+ STATUSOR_VOIDPTR sor = nullptr;
+ *sor;
+ }
+ )cc");
+
+ ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_access_test_defs.h"
+
+ void target() {
+ STATUSOR_VOIDPTR sor(nullptr);
+ *sor;
+ }
+ )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, InPlaceConstruct) {
+ ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_access_test_defs.h"
+
+ void target() {
+ STATUSOR_VOIDPTR absl_sor(absl::in_place, {nullptr});
+ *absl_sor;
+ STATUSOR_VOIDPTR std_sor(std::in_place, {nullptr});
+ *std_sor;
+ }
+ )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, ConstructStatusOrFromReference) {
+ ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_access_test_defs.h"
+ void target() {
+ const auto sor1 = Make<STATUSOR_INT&>();
+ const auto sor2 = Make<STATUSOR_INT&>();
+ if (!sor1.ok() && !sor2.ok()) return;
+ if (sor1.ok() && !sor2.ok()) {
+ } else if (!sor1.ok() && sor2.ok()) {
+ } else {
+ sor1.value();
+ sor2.value();
+ }
+ }
+ )cc");
+}
+
+TEST_P(UncheckedStatusOrAccessModelTest, ConstructStatusFromReference) {
+ ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_access_test_defs.h"
+
+ void target() {
+ const auto sor1 = Make<STATUSOR_INT&>();
+ const auto sor2 = Make<STATUSOR_INT&>();
+ const auto s1 = Make<STATUS&>();
+ const auto s2 = Make<STATUS&>();
+
+ if (!s1.ok() && !s2.ok()) return;
+ if (s1.ok() && !s2.ok()) {
+ } else if (!s1.ok() && s2.ok()) {
+ } else {
+ if (s1 != sor1.status() || s2 != sor2.status()) return;
+ sor1.value();
+ sor2.value();
+ }
+ }
+ )cc");
+}
+
} // namespace
std::string
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index ce68f91..d45babe 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -19615,6 +19615,25 @@ TEST_F(FormatTest, AlignConsecutiveAssignments) {
"};",
Alignment);
+ // Aligning lines should not mess up the comments. However, feel free to
+ // change the test if it turns out that comments inside the closure should not
+ // be aligned with those outside it.
+ verifyFormat("auto aaaaaaaaaaaaaaaaaaaaa = {}; //\n"
+ "auto b = [] { //\n"
+ " return; //\n"
+ "};",
+ Alignment);
+ verifyFormat("auto aaaaaaaaaaaaaaaaaaaaa = {}; //\n"
+ "auto b = [] { //\n"
+ " return aaaaaaaaaaaaaaaaaaaaa; //\n"
+ "};",
+ Alignment);
+ verifyFormat("auto aaaaaaaaaaaaaaa = {}; //\n"
+ "auto b = [] { //\n"
+ " return aaaaaaaaaaaaaaaaaaaaa; //\n"
+ "};",
+ Alignment);
+
verifyFormat("auto b = f(aaaaaaaaaaaaaaaaaaaaaaaaa,\n"
" ccc ? aaaaa : bbbbb,\n"
" dddddddddddddddddddddddddd);",