Index: clang/lib/AST/ExprConstant.cpp =================================================================== --- clang/lib/AST/ExprConstant.cpp +++ clang/lib/AST/ExprConstant.cpp @@ -12947,13 +12947,12 @@ if ((!LHSValue.Base && !LHSValue.Offset.isZero()) || (!RHSValue.Base && !RHSValue.Offset.isZero())) return Error(E); - // It's implementation-defined whether distinct literals will have - // distinct addresses. In clang, the result of such a comparison is - // unspecified, so it is not a constant expression. However, we do know - // that the address of a literal will be non-null. - if ((IsLiteralLValue(LHSValue) || IsLiteralLValue(RHSValue)) && - LHSValue.Base && RHSValue.Base) + + // ObjC's @encode() + if (isa(E->getLHS()->IgnoreParenImpCasts()) || + isa(E->getRHS()->IgnoreParenImpCasts())) return Error(E); + // We can't tell whether weak symbols will end up pointing to the same // object. if (IsWeakLValue(LHSValue) || IsWeakLValue(RHSValue)) Index: clang/test/SemaCXX/builtins.cpp =================================================================== --- clang/test/SemaCXX/builtins.cpp +++ clang/test/SemaCXX/builtins.cpp @@ -47,7 +47,7 @@ void a(void) {} int n; void *p = __builtin_function_start(n); // expected-error {{argument must be a function}} -static_assert(__builtin_function_start(a) == a, ""); // expected-error {{static assertion expression is not an integral constant expression}} +static_assert(__builtin_function_start(a) == a, ""); // expected-error {{static assertion failed}} } // namespace function_start void no_ms_builtins() { Index: clang/test/SemaCXX/constant-expression-cxx11.cpp =================================================================== --- clang/test/SemaCXX/constant-expression-cxx11.cpp +++ clang/test/SemaCXX/constant-expression-cxx11.cpp @@ -358,12 +358,29 @@ extern char externalvar[]; constexpr bool constaddress = (void *)externalvar == (void *)0x4000UL; // expected-error {{must be initialized by a constant expression}} expected-note {{reinterpret_cast}} -constexpr bool litaddress = "foo" == "foo"; // expected-error {{must be initialized by a constant expression}} -// cxx20_2b-warning@-1 {{comparison between two arrays is deprecated}} +constexpr bool litaddress = "foo" == "foo"; // cxx20_2b-warning {{comparison between two arrays is deprecated}} static_assert(0 != "foo", ""); } +constexpr const char *foo(const char *p) { return p; } +constexpr const char *p1 = "test1"; +constexpr const char *p2 = "test2"; + +constexpr bool b1 = foo(p1) == foo(p1); +static_assert(b1, ""); + +constexpr bool b2 = foo(p1) == foo(p2); +static_assert(!b2, ""); + +constexpr const char *name1() { return "name1"; } +constexpr const char *name2() { return "name2"; } + +constexpr auto b3 = name1() == name1(); +static_assert(b3, ""); +constexpr auto b4 = name1() == name2(); +static_assert(!b4, ""); + namespace MaterializeTemporary { constexpr int f(const int &r) { return r; } Index: clang/test/SemaCXX/constant-expression-cxx14.cpp =================================================================== --- clang/test/SemaCXX/constant-expression-cxx14.cpp +++ clang/test/SemaCXX/constant-expression-cxx14.cpp @@ -1274,3 +1274,12 @@ (dbt2.wp = nullptr, 0) }; } + + +constexpr auto name1() { return "name1"; } +constexpr auto name2() { return "name2"; } + +constexpr auto b3 = name1() == name1(); +static_assert(b3, ""); +constexpr auto b4 = name1() == name2(); +static_assert(!b4, "");