[clang] [clang] fix classification of a string literal expression used as initializer (PR #101447)

via cfe-commits cfe-commits at lists.llvm.org
Wed Jul 31 20:06:55 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Matheus Izvekov (mizvekov)

<details>
<summary>Changes</summary>

Since 3bf72d7d64b8465acd4f4af1a469d68d9dc86058 we have made a simplification where we transform a string literal into a prvalue, where normally they would always be lvalues.

This patch fixes expression classification to account for this case.

Fixes #<!-- -->82167

---
Full diff: https://github.com/llvm/llvm-project/pull/101447.diff


3 Files Affected:

- (modified) clang/docs/ReleaseNotes.rst (+3-1) 
- (modified) clang/lib/AST/ExprClassification.cpp (+6-2) 
- (added) clang/test/SemaCXX/GH82167.cpp (+15) 


``````````diff
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 3c2e0282d1c72..c4dca7252e87a 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -130,7 +130,7 @@ Improvements to Clang's diagnostics
 - Some template related diagnostics have been improved.
 
   .. code-block:: c++
-    
+
      void foo() { template <typename> int i; } // error: templates can only be declared in namespace or class scope
 
      struct S {
@@ -170,6 +170,8 @@ Bug Fixes to C++ Support
 - Fixed a failed assertion when checking invalid delete operator declaration. (#GH96191)
 - Fix a crash when checking destructor reference with an invalid initializer. (#GH97230)
 - Clang now correctly parses potentially declarative nested-name-specifiers in pointer-to-member declarators.
+- Fix a crash when checking the initialzier of an object that was initialized
+  with a string literal. (#GH82167)
 
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/AST/ExprClassification.cpp b/clang/lib/AST/ExprClassification.cpp
index 6482cb6d39acc..3b3c0af826079 100644
--- a/clang/lib/AST/ExprClassification.cpp
+++ b/clang/lib/AST/ExprClassification.cpp
@@ -119,8 +119,6 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
 
     // First come the expressions that are always lvalues, unconditionally.
   case Expr::ObjCIsaExprClass:
-    // C++ [expr.prim.general]p1: A string literal is an lvalue.
-  case Expr::StringLiteralClass:
     // @encode is equivalent to its string
   case Expr::ObjCEncodeExprClass:
     // __func__ and friends are too.
@@ -150,6 +148,12 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
   case Expr::OMPIteratorExprClass:
     return Cl::CL_LValue;
 
+    // C++ [expr.prim.general]p1: A string literal is an lvalue.
+    // Except we special case them as prvalues when they are used for
+    // initialization.
+  case Expr::StringLiteralClass:
+    return E->isLValue() ? Cl::CL_LValue : Cl::CL_PRValue;
+
     // C99 6.5.2.5p5 says that compound literals are lvalues.
     // In C++, they're prvalue temporaries, except for file-scope arrays.
   case Expr::CompoundLiteralExprClass:
diff --git a/clang/test/SemaCXX/GH82167.cpp b/clang/test/SemaCXX/GH82167.cpp
new file mode 100644
index 0000000000000..0e13a5a3e1b6d
--- /dev/null
+++ b/clang/test/SemaCXX/GH82167.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++23 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+namespace t1 {
+  struct array {
+    char elems[2];
+  };
+
+  template <unsigned> struct Literal {
+    array arr;
+    constexpr Literal() : arr("") {}
+  };
+
+  template struct Literal<0>;
+} // namespace t1

``````````

</details>


https://github.com/llvm/llvm-project/pull/101447


More information about the cfe-commits mailing list