[clang] [clang] Placement new error when modifying consts (PR #132460)

2025-03-24 Thread marius doerner via cfe-commits

https://github.com/mariusdr updated 
https://github.com/llvm/llvm-project/pull/132460

>From d4af25b14fb21f50c3771cce4595ca5c1bb920a7 Mon Sep 17 00:00:00 2001
From: marius doerner 
Date: Fri, 21 Mar 2025 20:19:57 +0100
Subject: [PATCH 1/3] [clang] Placement new error when modifying consts

Raise an error when placement new is used to modify a const-qualified
variable in a constexpr function.
---
 clang/lib/AST/ExprConstant.cpp|  9 ++
 clang/test/AST/ByteCode/placement-new.cpp | 39 +++
 2 files changed, 48 insertions(+)

diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 92a28897cf3ee..b4fc3d4471064 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -10415,7 +10415,16 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const 
CXXNewExpr *E) {
 
   typedef bool result_type;
   bool failed() { return false; }
+  bool checkConst(QualType QT) {
+if (QT.isConstQualified()) {
+  Info.FFDiag(E, diag::note_constexpr_modify_const_type) << QT;
+  return false;
+}
+return true;
+  }
   bool found(APValue &Subobj, QualType SubobjType) {
+if (!checkConst(SubobjType))
+  return false;
 // FIXME: Reject the cases where [basic.life]p8 would not permit the
 // old name of the object to be used to name the new object.
 unsigned SubobjectSize = 1;
diff --git a/clang/test/AST/ByteCode/placement-new.cpp 
b/clang/test/AST/ByteCode/placement-new.cpp
index c353162a7aab0..9b12c9f2b1714 100644
--- a/clang/test/AST/ByteCode/placement-new.cpp
+++ b/clang/test/AST/ByteCode/placement-new.cpp
@@ -376,3 +376,42 @@ constexpr int N = [] // expected-error {{must be 
initialized by a constant expre
 return s.a[0];
 }();
 #endif
+
+constexpr int modify_const_variable() {
+  const int a = 10;
+  new ((int *)&a) int(12); // both-note {{modification of object of 
const-qualified type 'const int' is not allowed in a constant expression}}
+  return a;
+}
+static_assert(modify_const_variable()); // both-error {{not an integral 
constant expression}} \
+// both-note {{in call to}}
+
+typedef const int T0;
+typedef T0 T1;
+constexpr T1 modify_const_variable_td() {
+  T1 a = 10;
+  new ((int *)&a) int(12); // both-note {{modification of object of 
const-qualified type 'T1' (aka 'const int') is not allowed in a constant 
expression}}
+  return a;
+}
+static_assert(modify_const_variable_td()); // both-error {{not an integral 
constant expression}} \
+   // both-note {{in call to}}
+
+template
+constexpr T modify_const_variable_tmpl() {
+  T a = 10;
+  new ((int *)&a) int(12); // both-note {{modification of object of 
const-qualified type 'const int' is not allowed in a constant expression}}
+  return a;
+}
+static_assert(modify_const_variable_tmpl()); // both-error {{not an 
integral constant expression}} \
+// both-note {{in call 
to}}
+
+namespace ModifyMutableMember {
+  struct S {
+mutable int a {10};
+  };
+  constexpr int modify_mutable_member() {
+const S s;
+new ((int *)&s.a) int(12);
+return s.a;
+  }
+  static_assert(modify_mutable_member() == 12);
+}

>From 197063860b652ba93ee3baab8b6213bb5dc809de Mon Sep 17 00:00:00 2001
From: marius doerner 
Date: Sun, 23 Mar 2025 09:21:34 +0100
Subject: [PATCH 2/3] Move tests from Ast/Bytecode to SemaCxx

---
 clang/test/AST/ByteCode/placement-new.cpp | 39 ---
 .../SemaCXX/cxx2c-constexpr-placement-new.cpp | 39 +++
 2 files changed, 39 insertions(+), 39 deletions(-)

diff --git a/clang/test/AST/ByteCode/placement-new.cpp 
b/clang/test/AST/ByteCode/placement-new.cpp
index 9b12c9f2b1714..c353162a7aab0 100644
--- a/clang/test/AST/ByteCode/placement-new.cpp
+++ b/clang/test/AST/ByteCode/placement-new.cpp
@@ -376,42 +376,3 @@ constexpr int N = [] // expected-error {{must be 
initialized by a constant expre
 return s.a[0];
 }();
 #endif
-
-constexpr int modify_const_variable() {
-  const int a = 10;
-  new ((int *)&a) int(12); // both-note {{modification of object of 
const-qualified type 'const int' is not allowed in a constant expression}}
-  return a;
-}
-static_assert(modify_const_variable()); // both-error {{not an integral 
constant expression}} \
-// both-note {{in call to}}
-
-typedef const int T0;
-typedef T0 T1;
-constexpr T1 modify_const_variable_td() {
-  T1 a = 10;
-  new ((int *)&a) int(12); // both-note {{modification of object of 
const-qualified type 'T1' (aka 'const int') is not allowed in a constant 
expression}}
-  return a;
-}
-static_assert(modify_const_variable_td()); // both-error {{not an integral 
constant expression}} \
-   // both-note {{in call to}}
-
-template
-constexpr T modify_const_variable_tmpl() {
-  T a = 10;
-  n

[clang] [clang] Clear `NeedsCleaning` flag after `ExpandBuiltinMacro` (PR #133574)

2025-04-05 Thread marius doerner via cfe-commits

https://github.com/mariusdr edited 
https://github.com/llvm/llvm-project/pull/133574
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Placement new error when modifying consts (PR #132460)

2025-03-26 Thread marius doerner via cfe-commits

https://github.com/mariusdr created 
https://github.com/llvm/llvm-project/pull/132460

Closes #131432

Raise an error when placement new is used to modify a const-qualified variable 
in a constexpr function. 

Note that diag::note_constexpr_modify_const_type is used since the it is also 
raised when the sample program is compiled with 
'-fexperimental-new-constant-interpreter'.

>From d4af25b14fb21f50c3771cce4595ca5c1bb920a7 Mon Sep 17 00:00:00 2001
From: marius doerner 
Date: Fri, 21 Mar 2025 20:19:57 +0100
Subject: [PATCH] [clang] Placement new error when modifying consts

Raise an error when placement new is used to modify a const-qualified
variable in a constexpr function.
---
 clang/lib/AST/ExprConstant.cpp|  9 ++
 clang/test/AST/ByteCode/placement-new.cpp | 39 +++
 2 files changed, 48 insertions(+)

diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 92a28897cf3ee..b4fc3d4471064 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -10415,7 +10415,16 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const 
CXXNewExpr *E) {
 
   typedef bool result_type;
   bool failed() { return false; }
+  bool checkConst(QualType QT) {
+if (QT.isConstQualified()) {
+  Info.FFDiag(E, diag::note_constexpr_modify_const_type) << QT;
+  return false;
+}
+return true;
+  }
   bool found(APValue &Subobj, QualType SubobjType) {
+if (!checkConst(SubobjType))
+  return false;
 // FIXME: Reject the cases where [basic.life]p8 would not permit the
 // old name of the object to be used to name the new object.
 unsigned SubobjectSize = 1;
diff --git a/clang/test/AST/ByteCode/placement-new.cpp 
b/clang/test/AST/ByteCode/placement-new.cpp
index c353162a7aab0..9b12c9f2b1714 100644
--- a/clang/test/AST/ByteCode/placement-new.cpp
+++ b/clang/test/AST/ByteCode/placement-new.cpp
@@ -376,3 +376,42 @@ constexpr int N = [] // expected-error {{must be 
initialized by a constant expre
 return s.a[0];
 }();
 #endif
+
+constexpr int modify_const_variable() {
+  const int a = 10;
+  new ((int *)&a) int(12); // both-note {{modification of object of 
const-qualified type 'const int' is not allowed in a constant expression}}
+  return a;
+}
+static_assert(modify_const_variable()); // both-error {{not an integral 
constant expression}} \
+// both-note {{in call to}}
+
+typedef const int T0;
+typedef T0 T1;
+constexpr T1 modify_const_variable_td() {
+  T1 a = 10;
+  new ((int *)&a) int(12); // both-note {{modification of object of 
const-qualified type 'T1' (aka 'const int') is not allowed in a constant 
expression}}
+  return a;
+}
+static_assert(modify_const_variable_td()); // both-error {{not an integral 
constant expression}} \
+   // both-note {{in call to}}
+
+template
+constexpr T modify_const_variable_tmpl() {
+  T a = 10;
+  new ((int *)&a) int(12); // both-note {{modification of object of 
const-qualified type 'const int' is not allowed in a constant expression}}
+  return a;
+}
+static_assert(modify_const_variable_tmpl()); // both-error {{not an 
integral constant expression}} \
+// both-note {{in call 
to}}
+
+namespace ModifyMutableMember {
+  struct S {
+mutable int a {10};
+  };
+  constexpr int modify_mutable_member() {
+const S s;
+new ((int *)&s.a) int(12);
+return s.a;
+  }
+  static_assert(modify_mutable_member() == 12);
+}

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Placement new error when modifying consts (PR #132460)

2025-03-25 Thread marius doerner via cfe-commits

mariusdr wrote:

> Thanks. Will you need me to merge that for you?

Yes, please

https://github.com/llvm/llvm-project/pull/132460
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Clear `NeedsCleaning` flag after `ExpandBuiltinMacro` (PR #133574)

2025-03-31 Thread marius doerner via cfe-commits

https://github.com/mariusdr edited 
https://github.com/llvm/llvm-project/pull/133574
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Clear `NeedsCleaning` flag after `ExpandBuiltinMacro` (PR #133574)

2025-03-31 Thread marius doerner via cfe-commits

https://github.com/mariusdr edited 
https://github.com/llvm/llvm-project/pull/133574
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Clear `NeedsCleaning` flag after `ExpandBuiltinMacro` (PR #133574)

2025-03-31 Thread marius doerner via cfe-commits

https://github.com/mariusdr updated 
https://github.com/llvm/llvm-project/pull/133574

>From dd54aa59eabe9c3b7b110f46d82ff5c4d0b88c57 Mon Sep 17 00:00:00 2001
From: marius doerner 
Date: Sat, 29 Mar 2025 09:21:20 +0100
Subject: [PATCH 1/2] [clang] Clear `NeedsCleaning` flag after
 `ExpandBuiltinMacro`

After builtin macro expansion in `Preprocessor::ExpandBuiltinMacro`
the result token may have the `Token::NeedsCleaning` flag set
which causes an assertion failure later on when the lexer retrives
the spelling of the token in `getSpellingSlow` in Lexer.cpp.
---
 clang/lib/Lex/PPMacroExpansion.cpp  |  2 +-
 clang/test/Preprocessor/embed___has_embed.c | 19 
 clang/test/Preprocessor/has_attribute.c | 20 +
 clang/test/Preprocessor/has_attribute.cpp   | 20 +
 clang/test/Preprocessor/has_c_attribute.c   | 20 +
 clang/test/Preprocessor/has_include.c   | 49 +
 6 files changed, 129 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Lex/PPMacroExpansion.cpp 
b/clang/lib/Lex/PPMacroExpansion.cpp
index 8e35d56d3f1a6..107d5c31e039d 100644
--- a/clang/lib/Lex/PPMacroExpansion.cpp
+++ b/clang/lib/Lex/PPMacroExpansion.cpp
@@ -1646,7 +1646,6 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
 
   // Set up the return result.
   Tok.setIdentifierInfo(nullptr);
-  Tok.clearFlag(Token::NeedsCleaning);
   bool IsAtStartOfLine = Tok.isAtStartOfLine();
   bool HasLeadingSpace = Tok.hasLeadingSpace();
 
@@ -2089,6 +2088,7 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
   CreateString(OS.str(), Tok, Tok.getLocation(), Tok.getLocation());
   Tok.setFlagValue(Token::StartOfLine, IsAtStartOfLine);
   Tok.setFlagValue(Token::LeadingSpace, HasLeadingSpace);
+  Tok.clearFlag(Token::NeedsCleaning);
 }
 
 void Preprocessor::markMacroAsUsed(MacroInfo *MI) {
diff --git a/clang/test/Preprocessor/embed___has_embed.c 
b/clang/test/Preprocessor/embed___has_embed.c
index 43a3068b5f53a..2705b5ef6fd5b 100644
--- a/clang/test/Preprocessor/embed___has_embed.c
+++ b/clang/test/Preprocessor/embed___has_embed.c
@@ -58,3 +58,22 @@ unsigned char buffer[] = {
 #else
 #error 17
 #endif
+
+#if __has_embed(__FILE__\
+)
+#else
+#error 18
+#endif
+
+#define F __FI\
+LE__
+#if __has_embed(F)
+#else
+#error 19
+#endif
+
+#if __has_embed(F\
+)
+#else 
+#error 20
+#endif
diff --git a/clang/test/Preprocessor/has_attribute.c 
b/clang/test/Preprocessor/has_attribute.c
index 0ba664a53e649..6f6f519bd299d 100644
--- a/clang/test/Preprocessor/has_attribute.c
+++ b/clang/test/Preprocessor/has_attribute.c
@@ -68,3 +68,23 @@ int has_no_volatile_attribute();
 int has_fallthrough;
 #endif
 // CHECK: int has_fallthrough;
+
+#if __has_attribute(F\
+)
+int has_fallthrough_2;
+#endif
+// CHECK: int has_fallthrough_2;
+
+#define F_2 fall\
+through
+
+#if __has_attribute(F_2)
+int has_fallthrough_3;
+#endif
+// CHECK: int has_fallthrough_3;
+
+#if __has_attribute(F_2\
+)
+int has_fallthrough_4;
+#endif
+// CHECK: int has_fallthrough_4;
diff --git a/clang/test/Preprocessor/has_attribute.cpp 
b/clang/test/Preprocessor/has_attribute.cpp
index 00ec57615c84b..72af6de27e8bb 100644
--- a/clang/test/Preprocessor/has_attribute.cpp
+++ b/clang/test/Preprocessor/has_attribute.cpp
@@ -116,6 +116,26 @@ int funclike_1;
 int funclike_2;
 #endif
 // CHECK: int funclike_2;
+
+#if __has_cpp_attribute(CF\
+)
+int has_clang_falthrough_5;
+#endif
+// CHECK: int has_clang_falthrough_5;
+
+#define CF_2 clang::\
+fallthrough
+
+#if __has_cpp_attribute(CF_2)
+int has_clang_falthrough_6;
+#endif
+// CHECK: int has_clang_falthrough_6;
+
+#if __has_cpp_attribute(CF_2\
+)
+int has_clang_falthrough_7;
+#endif
+// CHECK: int has_clang_falthrough_7;
 }
 
 // Test for Microsoft __declspec attributes
diff --git a/clang/test/Preprocessor/has_c_attribute.c 
b/clang/test/Preprocessor/has_c_attribute.c
index 3332571d758c8..d8be13f5898a9 100644
--- a/clang/test/Preprocessor/has_c_attribute.c
+++ b/clang/test/Preprocessor/has_c_attribute.c
@@ -84,3 +84,23 @@ int funclike_1;
 int funclike_2;
 #endif
 // CHECK: int funclike_2;
+
+#if __has_c_attribute(CL\
+)
+int has_clang_likely_5;
+#endif
+// CHECK: int has_clang_likely_5;
+
+#define CL_2 clang::\
+likely
+
+#if __has_c_attribute(CL_2)
+int has_clang_likely_6;
+#endif
+// CHECK: int has_clang_likely_6;
+
+#if __has_c_attribute(CL_2\
+)
+int has_clang_likely_7;
+#endif
+// CHECK: int has_clang_likely_7;
diff --git a/clang/test/Preprocessor/has_include.c 
b/clang/test/Preprocessor/has_include.c
index c95025d83860a..ff199bf23063f 100644
--- a/clang/test/Preprocessor/has_include.c
+++ b/clang/test/Preprocessor/has_include.c
@@ -197,3 +197,52 @@ __has_include
 #ifdef FOO
 #elif __has_include()
 #endif
+
+#if __has_include(\
+)
+#else
+  #error "__has_include failed (10)."
+#endif
+
+#define MACRO6 
+#if __has_include(MACRO6\
+)
+#else
+  #error "__has_include failed (11)."
+#endif
+
+#if __has_include_next(/*expected-warning {{#include_next in primary 
source file}}*/\
+)
+#else
+  #error "__has_

[clang] [clang] Clear `NeedsCleaning` flag after `ExpandBuiltinMacro` (PR #133574)

2025-03-31 Thread marius doerner via cfe-commits


@@ -1646,7 +1646,6 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
 
   // Set up the return result.
   Tok.setIdentifierInfo(nullptr);
-  Tok.clearFlag(Token::NeedsCleaning);

mariusdr wrote:

True, my bad. If the flag is removed we can get asserts on __DATE__ and 
__TIME__ expansion. I've put it back and added some test cases to account for 
this (also for some similar macros like __LINE__, __FILE__ which do not early 
return but are easily tested in the same way). 

https://github.com/llvm/llvm-project/pull/133574
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Clear `NeedsCleaning` flag after `ExpandBuiltinMacro` (PR #133574)

2025-04-15 Thread marius doerner via cfe-commits

https://github.com/mariusdr updated 
https://github.com/llvm/llvm-project/pull/133574

>From bcf038103c717edfdcf633ac8f3f6f1f306d927a Mon Sep 17 00:00:00 2001
From: marius doerner 
Date: Sat, 29 Mar 2025 09:21:20 +0100
Subject: [PATCH 1/3] [clang] Clear `NeedsCleaning` flag after
 `ExpandBuiltinMacro`

After builtin macro expansion in `Preprocessor::ExpandBuiltinMacro`
the result token may have the `Token::NeedsCleaning` flag set
which causes an assertion failure later on when the lexer retrives
the spelling of the token in `getSpellingSlow` in Lexer.cpp.
---
 clang/lib/Lex/PPMacroExpansion.cpp  |  2 +-
 clang/test/Preprocessor/embed___has_embed.c | 19 
 clang/test/Preprocessor/has_attribute.c | 20 +
 clang/test/Preprocessor/has_attribute.cpp   | 20 +
 clang/test/Preprocessor/has_c_attribute.c   | 20 +
 clang/test/Preprocessor/has_include.c   | 49 +
 6 files changed, 129 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Lex/PPMacroExpansion.cpp 
b/clang/lib/Lex/PPMacroExpansion.cpp
index 8e35d56d3f1a6..107d5c31e039d 100644
--- a/clang/lib/Lex/PPMacroExpansion.cpp
+++ b/clang/lib/Lex/PPMacroExpansion.cpp
@@ -1646,7 +1646,6 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
 
   // Set up the return result.
   Tok.setIdentifierInfo(nullptr);
-  Tok.clearFlag(Token::NeedsCleaning);
   bool IsAtStartOfLine = Tok.isAtStartOfLine();
   bool HasLeadingSpace = Tok.hasLeadingSpace();
 
@@ -2089,6 +2088,7 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
   CreateString(OS.str(), Tok, Tok.getLocation(), Tok.getLocation());
   Tok.setFlagValue(Token::StartOfLine, IsAtStartOfLine);
   Tok.setFlagValue(Token::LeadingSpace, HasLeadingSpace);
+  Tok.clearFlag(Token::NeedsCleaning);
 }
 
 void Preprocessor::markMacroAsUsed(MacroInfo *MI) {
diff --git a/clang/test/Preprocessor/embed___has_embed.c 
b/clang/test/Preprocessor/embed___has_embed.c
index 43a3068b5f53a..2705b5ef6fd5b 100644
--- a/clang/test/Preprocessor/embed___has_embed.c
+++ b/clang/test/Preprocessor/embed___has_embed.c
@@ -58,3 +58,22 @@ unsigned char buffer[] = {
 #else
 #error 17
 #endif
+
+#if __has_embed(__FILE__\
+)
+#else
+#error 18
+#endif
+
+#define F __FI\
+LE__
+#if __has_embed(F)
+#else
+#error 19
+#endif
+
+#if __has_embed(F\
+)
+#else 
+#error 20
+#endif
diff --git a/clang/test/Preprocessor/has_attribute.c 
b/clang/test/Preprocessor/has_attribute.c
index 0ba664a53e649..6f6f519bd299d 100644
--- a/clang/test/Preprocessor/has_attribute.c
+++ b/clang/test/Preprocessor/has_attribute.c
@@ -68,3 +68,23 @@ int has_no_volatile_attribute();
 int has_fallthrough;
 #endif
 // CHECK: int has_fallthrough;
+
+#if __has_attribute(F\
+)
+int has_fallthrough_2;
+#endif
+// CHECK: int has_fallthrough_2;
+
+#define F_2 fall\
+through
+
+#if __has_attribute(F_2)
+int has_fallthrough_3;
+#endif
+// CHECK: int has_fallthrough_3;
+
+#if __has_attribute(F_2\
+)
+int has_fallthrough_4;
+#endif
+// CHECK: int has_fallthrough_4;
diff --git a/clang/test/Preprocessor/has_attribute.cpp 
b/clang/test/Preprocessor/has_attribute.cpp
index 00ec57615c84b..72af6de27e8bb 100644
--- a/clang/test/Preprocessor/has_attribute.cpp
+++ b/clang/test/Preprocessor/has_attribute.cpp
@@ -116,6 +116,26 @@ int funclike_1;
 int funclike_2;
 #endif
 // CHECK: int funclike_2;
+
+#if __has_cpp_attribute(CF\
+)
+int has_clang_falthrough_5;
+#endif
+// CHECK: int has_clang_falthrough_5;
+
+#define CF_2 clang::\
+fallthrough
+
+#if __has_cpp_attribute(CF_2)
+int has_clang_falthrough_6;
+#endif
+// CHECK: int has_clang_falthrough_6;
+
+#if __has_cpp_attribute(CF_2\
+)
+int has_clang_falthrough_7;
+#endif
+// CHECK: int has_clang_falthrough_7;
 }
 
 // Test for Microsoft __declspec attributes
diff --git a/clang/test/Preprocessor/has_c_attribute.c 
b/clang/test/Preprocessor/has_c_attribute.c
index 3332571d758c8..d8be13f5898a9 100644
--- a/clang/test/Preprocessor/has_c_attribute.c
+++ b/clang/test/Preprocessor/has_c_attribute.c
@@ -84,3 +84,23 @@ int funclike_1;
 int funclike_2;
 #endif
 // CHECK: int funclike_2;
+
+#if __has_c_attribute(CL\
+)
+int has_clang_likely_5;
+#endif
+// CHECK: int has_clang_likely_5;
+
+#define CL_2 clang::\
+likely
+
+#if __has_c_attribute(CL_2)
+int has_clang_likely_6;
+#endif
+// CHECK: int has_clang_likely_6;
+
+#if __has_c_attribute(CL_2\
+)
+int has_clang_likely_7;
+#endif
+// CHECK: int has_clang_likely_7;
diff --git a/clang/test/Preprocessor/has_include.c 
b/clang/test/Preprocessor/has_include.c
index c95025d83860a..ff199bf23063f 100644
--- a/clang/test/Preprocessor/has_include.c
+++ b/clang/test/Preprocessor/has_include.c
@@ -197,3 +197,52 @@ __has_include
 #ifdef FOO
 #elif __has_include()
 #endif
+
+#if __has_include(\
+)
+#else
+  #error "__has_include failed (10)."
+#endif
+
+#define MACRO6 
+#if __has_include(MACRO6\
+)
+#else
+  #error "__has_include failed (11)."
+#endif
+
+#if __has_include_next(/*expected-warning {{#include_next in primary 
source file}}*/\
+)
+#else
+  #error "__has_

[clang] [clang] Clear `NeedsCleaning` flag after `ExpandBuiltinMacro` (PR #133574)

2025-04-15 Thread marius doerner via cfe-commits

mariusdr wrote:

> LGTM - sorry for the delayed response.
> 
> Will you need me to merge that for you (once the merge conflict is resolved)?

Yes, thanks!

https://github.com/llvm/llvm-project/pull/133574
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Placement new error when modifying consts (PR #132460)

2025-04-04 Thread marius doerner via cfe-commits

mariusdr wrote:

Added release notes under "Bug Fixes to C++ Support". Thanks for the review.

https://github.com/llvm/llvm-project/pull/132460
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Placement new error when modifying consts (PR #132460)

2025-03-23 Thread marius doerner via cfe-commits

mariusdr wrote:

> The tests should go into a file not under `ByteCode/` since they aren't 
> specific to the bytecode interpreter. There should be existing placement new 
> tests in `SemaCXX/`.

Thanks for the hint, moved them to 
clang/test/SemaCXX/cxx2c-constexpr-placement-new.cpp

https://github.com/llvm/llvm-project/pull/132460
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Placement new error when modifying consts (PR #132460)

2025-03-23 Thread marius doerner via cfe-commits

https://github.com/mariusdr updated 
https://github.com/llvm/llvm-project/pull/132460

>From d4af25b14fb21f50c3771cce4595ca5c1bb920a7 Mon Sep 17 00:00:00 2001
From: marius doerner 
Date: Fri, 21 Mar 2025 20:19:57 +0100
Subject: [PATCH 1/2] [clang] Placement new error when modifying consts

Raise an error when placement new is used to modify a const-qualified
variable in a constexpr function.
---
 clang/lib/AST/ExprConstant.cpp|  9 ++
 clang/test/AST/ByteCode/placement-new.cpp | 39 +++
 2 files changed, 48 insertions(+)

diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 92a28897cf3ee..b4fc3d4471064 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -10415,7 +10415,16 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const 
CXXNewExpr *E) {
 
   typedef bool result_type;
   bool failed() { return false; }
+  bool checkConst(QualType QT) {
+if (QT.isConstQualified()) {
+  Info.FFDiag(E, diag::note_constexpr_modify_const_type) << QT;
+  return false;
+}
+return true;
+  }
   bool found(APValue &Subobj, QualType SubobjType) {
+if (!checkConst(SubobjType))
+  return false;
 // FIXME: Reject the cases where [basic.life]p8 would not permit the
 // old name of the object to be used to name the new object.
 unsigned SubobjectSize = 1;
diff --git a/clang/test/AST/ByteCode/placement-new.cpp 
b/clang/test/AST/ByteCode/placement-new.cpp
index c353162a7aab0..9b12c9f2b1714 100644
--- a/clang/test/AST/ByteCode/placement-new.cpp
+++ b/clang/test/AST/ByteCode/placement-new.cpp
@@ -376,3 +376,42 @@ constexpr int N = [] // expected-error {{must be 
initialized by a constant expre
 return s.a[0];
 }();
 #endif
+
+constexpr int modify_const_variable() {
+  const int a = 10;
+  new ((int *)&a) int(12); // both-note {{modification of object of 
const-qualified type 'const int' is not allowed in a constant expression}}
+  return a;
+}
+static_assert(modify_const_variable()); // both-error {{not an integral 
constant expression}} \
+// both-note {{in call to}}
+
+typedef const int T0;
+typedef T0 T1;
+constexpr T1 modify_const_variable_td() {
+  T1 a = 10;
+  new ((int *)&a) int(12); // both-note {{modification of object of 
const-qualified type 'T1' (aka 'const int') is not allowed in a constant 
expression}}
+  return a;
+}
+static_assert(modify_const_variable_td()); // both-error {{not an integral 
constant expression}} \
+   // both-note {{in call to}}
+
+template
+constexpr T modify_const_variable_tmpl() {
+  T a = 10;
+  new ((int *)&a) int(12); // both-note {{modification of object of 
const-qualified type 'const int' is not allowed in a constant expression}}
+  return a;
+}
+static_assert(modify_const_variable_tmpl()); // both-error {{not an 
integral constant expression}} \
+// both-note {{in call 
to}}
+
+namespace ModifyMutableMember {
+  struct S {
+mutable int a {10};
+  };
+  constexpr int modify_mutable_member() {
+const S s;
+new ((int *)&s.a) int(12);
+return s.a;
+  }
+  static_assert(modify_mutable_member() == 12);
+}

>From b596108cb5f66f81bdc1a0809f91cfa9b4dad0a6 Mon Sep 17 00:00:00 2001
From: marius doerner 
Date: Sun, 23 Mar 2025 09:21:34 +0100
Subject: [PATCH 2/2] Move tests from Ast/Bytecode to SemaCxx

---
 clang/test/AST/ByteCode/placement-new.cpp | 39 ---
 .../SemaCXX/cxx2c-constexpr-placement-new.cpp | 39 +++
 2 files changed, 39 insertions(+), 39 deletions(-)

diff --git a/clang/test/AST/ByteCode/placement-new.cpp 
b/clang/test/AST/ByteCode/placement-new.cpp
index 9b12c9f2b1714..c353162a7aab0 100644
--- a/clang/test/AST/ByteCode/placement-new.cpp
+++ b/clang/test/AST/ByteCode/placement-new.cpp
@@ -376,42 +376,3 @@ constexpr int N = [] // expected-error {{must be 
initialized by a constant expre
 return s.a[0];
 }();
 #endif
-
-constexpr int modify_const_variable() {
-  const int a = 10;
-  new ((int *)&a) int(12); // both-note {{modification of object of 
const-qualified type 'const int' is not allowed in a constant expression}}
-  return a;
-}
-static_assert(modify_const_variable()); // both-error {{not an integral 
constant expression}} \
-// both-note {{in call to}}
-
-typedef const int T0;
-typedef T0 T1;
-constexpr T1 modify_const_variable_td() {
-  T1 a = 10;
-  new ((int *)&a) int(12); // both-note {{modification of object of 
const-qualified type 'T1' (aka 'const int') is not allowed in a constant 
expression}}
-  return a;
-}
-static_assert(modify_const_variable_td()); // both-error {{not an integral 
constant expression}} \
-   // both-note {{in call to}}
-
-template
-constexpr T modify_const_variable_tmpl() {
-  T a = 10;
-  n

[clang] [clang] Placement new error when modifying consts (PR #132460)

2025-03-23 Thread marius doerner via cfe-commits

https://github.com/mariusdr updated 
https://github.com/llvm/llvm-project/pull/132460

>From d4af25b14fb21f50c3771cce4595ca5c1bb920a7 Mon Sep 17 00:00:00 2001
From: marius doerner 
Date: Fri, 21 Mar 2025 20:19:57 +0100
Subject: [PATCH 1/2] [clang] Placement new error when modifying consts

Raise an error when placement new is used to modify a const-qualified
variable in a constexpr function.
---
 clang/lib/AST/ExprConstant.cpp|  9 ++
 clang/test/AST/ByteCode/placement-new.cpp | 39 +++
 2 files changed, 48 insertions(+)

diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 92a28897cf3ee..b4fc3d4471064 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -10415,7 +10415,16 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const 
CXXNewExpr *E) {
 
   typedef bool result_type;
   bool failed() { return false; }
+  bool checkConst(QualType QT) {
+if (QT.isConstQualified()) {
+  Info.FFDiag(E, diag::note_constexpr_modify_const_type) << QT;
+  return false;
+}
+return true;
+  }
   bool found(APValue &Subobj, QualType SubobjType) {
+if (!checkConst(SubobjType))
+  return false;
 // FIXME: Reject the cases where [basic.life]p8 would not permit the
 // old name of the object to be used to name the new object.
 unsigned SubobjectSize = 1;
diff --git a/clang/test/AST/ByteCode/placement-new.cpp 
b/clang/test/AST/ByteCode/placement-new.cpp
index c353162a7aab0..9b12c9f2b1714 100644
--- a/clang/test/AST/ByteCode/placement-new.cpp
+++ b/clang/test/AST/ByteCode/placement-new.cpp
@@ -376,3 +376,42 @@ constexpr int N = [] // expected-error {{must be 
initialized by a constant expre
 return s.a[0];
 }();
 #endif
+
+constexpr int modify_const_variable() {
+  const int a = 10;
+  new ((int *)&a) int(12); // both-note {{modification of object of 
const-qualified type 'const int' is not allowed in a constant expression}}
+  return a;
+}
+static_assert(modify_const_variable()); // both-error {{not an integral 
constant expression}} \
+// both-note {{in call to}}
+
+typedef const int T0;
+typedef T0 T1;
+constexpr T1 modify_const_variable_td() {
+  T1 a = 10;
+  new ((int *)&a) int(12); // both-note {{modification of object of 
const-qualified type 'T1' (aka 'const int') is not allowed in a constant 
expression}}
+  return a;
+}
+static_assert(modify_const_variable_td()); // both-error {{not an integral 
constant expression}} \
+   // both-note {{in call to}}
+
+template
+constexpr T modify_const_variable_tmpl() {
+  T a = 10;
+  new ((int *)&a) int(12); // both-note {{modification of object of 
const-qualified type 'const int' is not allowed in a constant expression}}
+  return a;
+}
+static_assert(modify_const_variable_tmpl()); // both-error {{not an 
integral constant expression}} \
+// both-note {{in call 
to}}
+
+namespace ModifyMutableMember {
+  struct S {
+mutable int a {10};
+  };
+  constexpr int modify_mutable_member() {
+const S s;
+new ((int *)&s.a) int(12);
+return s.a;
+  }
+  static_assert(modify_mutable_member() == 12);
+}

>From 197063860b652ba93ee3baab8b6213bb5dc809de Mon Sep 17 00:00:00 2001
From: marius doerner 
Date: Sun, 23 Mar 2025 09:21:34 +0100
Subject: [PATCH 2/2] Move tests from Ast/Bytecode to SemaCxx

---
 clang/test/AST/ByteCode/placement-new.cpp | 39 ---
 .../SemaCXX/cxx2c-constexpr-placement-new.cpp | 39 +++
 2 files changed, 39 insertions(+), 39 deletions(-)

diff --git a/clang/test/AST/ByteCode/placement-new.cpp 
b/clang/test/AST/ByteCode/placement-new.cpp
index 9b12c9f2b1714..c353162a7aab0 100644
--- a/clang/test/AST/ByteCode/placement-new.cpp
+++ b/clang/test/AST/ByteCode/placement-new.cpp
@@ -376,42 +376,3 @@ constexpr int N = [] // expected-error {{must be 
initialized by a constant expre
 return s.a[0];
 }();
 #endif
-
-constexpr int modify_const_variable() {
-  const int a = 10;
-  new ((int *)&a) int(12); // both-note {{modification of object of 
const-qualified type 'const int' is not allowed in a constant expression}}
-  return a;
-}
-static_assert(modify_const_variable()); // both-error {{not an integral 
constant expression}} \
-// both-note {{in call to}}
-
-typedef const int T0;
-typedef T0 T1;
-constexpr T1 modify_const_variable_td() {
-  T1 a = 10;
-  new ((int *)&a) int(12); // both-note {{modification of object of 
const-qualified type 'T1' (aka 'const int') is not allowed in a constant 
expression}}
-  return a;
-}
-static_assert(modify_const_variable_td()); // both-error {{not an integral 
constant expression}} \
-   // both-note {{in call to}}
-
-template
-constexpr T modify_const_variable_tmpl() {
-  T a = 10;
-  n

[clang] [clang] Clear `NeedsCleaning` flag after `ExpandBuiltinMacro` (PR #133574)

2025-03-29 Thread marius doerner via cfe-commits

https://github.com/mariusdr updated 
https://github.com/llvm/llvm-project/pull/133574

>From dd54aa59eabe9c3b7b110f46d82ff5c4d0b88c57 Mon Sep 17 00:00:00 2001
From: marius doerner 
Date: Sat, 29 Mar 2025 09:21:20 +0100
Subject: [PATCH] [clang] Clear `NeedsCleaning` flag after `ExpandBuiltinMacro`

After builtin macro expansion in `Preprocessor::ExpandBuiltinMacro`
the result token may have the `Token::NeedsCleaning` flag set
which causes an assertion failure later on when the lexer retrives
the spelling of the token in `getSpellingSlow` in Lexer.cpp.
---
 clang/lib/Lex/PPMacroExpansion.cpp  |  2 +-
 clang/test/Preprocessor/embed___has_embed.c | 19 
 clang/test/Preprocessor/has_attribute.c | 20 +
 clang/test/Preprocessor/has_attribute.cpp   | 20 +
 clang/test/Preprocessor/has_c_attribute.c   | 20 +
 clang/test/Preprocessor/has_include.c   | 49 +
 6 files changed, 129 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Lex/PPMacroExpansion.cpp 
b/clang/lib/Lex/PPMacroExpansion.cpp
index 8e35d56d3f1a6..107d5c31e039d 100644
--- a/clang/lib/Lex/PPMacroExpansion.cpp
+++ b/clang/lib/Lex/PPMacroExpansion.cpp
@@ -1646,7 +1646,6 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
 
   // Set up the return result.
   Tok.setIdentifierInfo(nullptr);
-  Tok.clearFlag(Token::NeedsCleaning);
   bool IsAtStartOfLine = Tok.isAtStartOfLine();
   bool HasLeadingSpace = Tok.hasLeadingSpace();
 
@@ -2089,6 +2088,7 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
   CreateString(OS.str(), Tok, Tok.getLocation(), Tok.getLocation());
   Tok.setFlagValue(Token::StartOfLine, IsAtStartOfLine);
   Tok.setFlagValue(Token::LeadingSpace, HasLeadingSpace);
+  Tok.clearFlag(Token::NeedsCleaning);
 }
 
 void Preprocessor::markMacroAsUsed(MacroInfo *MI) {
diff --git a/clang/test/Preprocessor/embed___has_embed.c 
b/clang/test/Preprocessor/embed___has_embed.c
index 43a3068b5f53a..2705b5ef6fd5b 100644
--- a/clang/test/Preprocessor/embed___has_embed.c
+++ b/clang/test/Preprocessor/embed___has_embed.c
@@ -58,3 +58,22 @@ unsigned char buffer[] = {
 #else
 #error 17
 #endif
+
+#if __has_embed(__FILE__\
+)
+#else
+#error 18
+#endif
+
+#define F __FI\
+LE__
+#if __has_embed(F)
+#else
+#error 19
+#endif
+
+#if __has_embed(F\
+)
+#else 
+#error 20
+#endif
diff --git a/clang/test/Preprocessor/has_attribute.c 
b/clang/test/Preprocessor/has_attribute.c
index 0ba664a53e649..6f6f519bd299d 100644
--- a/clang/test/Preprocessor/has_attribute.c
+++ b/clang/test/Preprocessor/has_attribute.c
@@ -68,3 +68,23 @@ int has_no_volatile_attribute();
 int has_fallthrough;
 #endif
 // CHECK: int has_fallthrough;
+
+#if __has_attribute(F\
+)
+int has_fallthrough_2;
+#endif
+// CHECK: int has_fallthrough_2;
+
+#define F_2 fall\
+through
+
+#if __has_attribute(F_2)
+int has_fallthrough_3;
+#endif
+// CHECK: int has_fallthrough_3;
+
+#if __has_attribute(F_2\
+)
+int has_fallthrough_4;
+#endif
+// CHECK: int has_fallthrough_4;
diff --git a/clang/test/Preprocessor/has_attribute.cpp 
b/clang/test/Preprocessor/has_attribute.cpp
index 00ec57615c84b..72af6de27e8bb 100644
--- a/clang/test/Preprocessor/has_attribute.cpp
+++ b/clang/test/Preprocessor/has_attribute.cpp
@@ -116,6 +116,26 @@ int funclike_1;
 int funclike_2;
 #endif
 // CHECK: int funclike_2;
+
+#if __has_cpp_attribute(CF\
+)
+int has_clang_falthrough_5;
+#endif
+// CHECK: int has_clang_falthrough_5;
+
+#define CF_2 clang::\
+fallthrough
+
+#if __has_cpp_attribute(CF_2)
+int has_clang_falthrough_6;
+#endif
+// CHECK: int has_clang_falthrough_6;
+
+#if __has_cpp_attribute(CF_2\
+)
+int has_clang_falthrough_7;
+#endif
+// CHECK: int has_clang_falthrough_7;
 }
 
 // Test for Microsoft __declspec attributes
diff --git a/clang/test/Preprocessor/has_c_attribute.c 
b/clang/test/Preprocessor/has_c_attribute.c
index 3332571d758c8..d8be13f5898a9 100644
--- a/clang/test/Preprocessor/has_c_attribute.c
+++ b/clang/test/Preprocessor/has_c_attribute.c
@@ -84,3 +84,23 @@ int funclike_1;
 int funclike_2;
 #endif
 // CHECK: int funclike_2;
+
+#if __has_c_attribute(CL\
+)
+int has_clang_likely_5;
+#endif
+// CHECK: int has_clang_likely_5;
+
+#define CL_2 clang::\
+likely
+
+#if __has_c_attribute(CL_2)
+int has_clang_likely_6;
+#endif
+// CHECK: int has_clang_likely_6;
+
+#if __has_c_attribute(CL_2\
+)
+int has_clang_likely_7;
+#endif
+// CHECK: int has_clang_likely_7;
diff --git a/clang/test/Preprocessor/has_include.c 
b/clang/test/Preprocessor/has_include.c
index c95025d83860a..ff199bf23063f 100644
--- a/clang/test/Preprocessor/has_include.c
+++ b/clang/test/Preprocessor/has_include.c
@@ -197,3 +197,52 @@ __has_include
 #ifdef FOO
 #elif __has_include()
 #endif
+
+#if __has_include(\
+)
+#else
+  #error "__has_include failed (10)."
+#endif
+
+#define MACRO6 
+#if __has_include(MACRO6\
+)
+#else
+  #error "__has_include failed (11)."
+#endif
+
+#if __has_include_next(/*expected-warning {{#include_next in primary 
source file}}*/\
+)
+#else
+  #error "__has_inclu

[clang] [clang] Clear `NeedsCleaning` flag after `ExpandBuiltinMacro` (PR #133574)

2025-03-29 Thread marius doerner via cfe-commits

https://github.com/mariusdr created 
https://github.com/llvm/llvm-project/pull/133574

After builtin macro expansion in `Preprocessor::ExpandBuiltinMacro` the result 
token may have the `Token::NeedsCleaning` flag set which causes an assertion 
failure later on when the lexer retrieves the spelling of the token in 
`getSpellingSlow`.

This commit moves the `Tok.clearFlag(Token::NeedsCleaning)` call to the end of 
`ExpandBuiltinMacro`.

Closes #128384 

>From ae2279bb0fa44ff290a3305b90598caf60284066 Mon Sep 17 00:00:00 2001
From: marius doerner 
Date: Sat, 29 Mar 2025 09:21:20 +0100
Subject: [PATCH] [clang] Clear `NeedsCleaning` flag after `ExpandBuiltinMacro`

After builtin macro expansion in `Preprocessor::ExpandBuiltinMacro`
the result token may have the `Token::NeedsCleaning` flag set
which causes an assertion failure later on when the lexer retrives
the spelling of the token in `getSpellingSlow` in Lexer.cpp.
---
 clang/lib/Lex/PPMacroExpansion.cpp  |  2 +-
 clang/test/Preprocessor/embed___has_embed.c | 19 
 clang/test/Preprocessor/has_attribute.c | 20 +
 clang/test/Preprocessor/has_attribute.cpp   | 20 +
 clang/test/Preprocessor/has_c_attribute.c   | 20 +
 clang/test/Preprocessor/has_include.c   | 49 +
 6 files changed, 129 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Lex/PPMacroExpansion.cpp 
b/clang/lib/Lex/PPMacroExpansion.cpp
index 8e35d56d3f1a6..107d5c31e039d 100644
--- a/clang/lib/Lex/PPMacroExpansion.cpp
+++ b/clang/lib/Lex/PPMacroExpansion.cpp
@@ -1646,7 +1646,6 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
 
   // Set up the return result.
   Tok.setIdentifierInfo(nullptr);
-  Tok.clearFlag(Token::NeedsCleaning);
   bool IsAtStartOfLine = Tok.isAtStartOfLine();
   bool HasLeadingSpace = Tok.hasLeadingSpace();
 
@@ -2089,6 +2088,7 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
   CreateString(OS.str(), Tok, Tok.getLocation(), Tok.getLocation());
   Tok.setFlagValue(Token::StartOfLine, IsAtStartOfLine);
   Tok.setFlagValue(Token::LeadingSpace, HasLeadingSpace);
+  Tok.clearFlag(Token::NeedsCleaning);
 }
 
 void Preprocessor::markMacroAsUsed(MacroInfo *MI) {
diff --git a/clang/test/Preprocessor/embed___has_embed.c 
b/clang/test/Preprocessor/embed___has_embed.c
index 43a3068b5f53a..2705b5ef6fd5b 100644
--- a/clang/test/Preprocessor/embed___has_embed.c
+++ b/clang/test/Preprocessor/embed___has_embed.c
@@ -58,3 +58,22 @@ unsigned char buffer[] = {
 #else
 #error 17
 #endif
+
+#if __has_embed(__FILE__\
+)
+#else
+#error 18
+#endif
+
+#define F __FI\
+LE__
+#if __has_embed(F)
+#else
+#error 19
+#endif
+
+#if __has_embed(F\
+)
+#else 
+#error 20
+#endif
diff --git a/clang/test/Preprocessor/has_attribute.c 
b/clang/test/Preprocessor/has_attribute.c
index 0ba664a53e649..6f6f519bd299d 100644
--- a/clang/test/Preprocessor/has_attribute.c
+++ b/clang/test/Preprocessor/has_attribute.c
@@ -68,3 +68,23 @@ int has_no_volatile_attribute();
 int has_fallthrough;
 #endif
 // CHECK: int has_fallthrough;
+
+#if __has_attribute(F\
+)
+int has_fallthrough_2;
+#endif
+// CHECK: int has_fallthrough_2;
+
+#define F_2 fall\
+through
+
+#if __has_attribute(F_2)
+int has_fallthrough_3;
+#endif
+// CHECK: int has_fallthrough_3;
+
+#if __has_attribute(F_2\
+)
+int has_fallthrough_4;
+#endif
+// CHECK: int has_fallthrough_4;
diff --git a/clang/test/Preprocessor/has_attribute.cpp 
b/clang/test/Preprocessor/has_attribute.cpp
index 00ec57615c84b..72af6de27e8bb 100644
--- a/clang/test/Preprocessor/has_attribute.cpp
+++ b/clang/test/Preprocessor/has_attribute.cpp
@@ -116,6 +116,26 @@ int funclike_1;
 int funclike_2;
 #endif
 // CHECK: int funclike_2;
+
+#if __has_cpp_attribute(CF\
+)
+int has_clang_falthrough_5;
+#endif
+// CHECK: int has_clang_falthrough_5;
+
+#define CF_2 clang::\
+fallthrough
+
+#if __has_cpp_attribute(CF_2)
+int has_clang_falthrough_6;
+#endif
+// CHECK: int has_clang_falthrough_6;
+
+#if __has_cpp_attribute(CF_2\
+)
+int has_clang_falthrough_7;
+#endif
+// CHECK: int has_clang_falthrough_7;
 }
 
 // Test for Microsoft __declspec attributes
diff --git a/clang/test/Preprocessor/has_c_attribute.c 
b/clang/test/Preprocessor/has_c_attribute.c
index 3332571d758c8..d8be13f5898a9 100644
--- a/clang/test/Preprocessor/has_c_attribute.c
+++ b/clang/test/Preprocessor/has_c_attribute.c
@@ -84,3 +84,23 @@ int funclike_1;
 int funclike_2;
 #endif
 // CHECK: int funclike_2;
+
+#if __has_c_attribute(CL\
+)
+int has_clang_likely_5;
+#endif
+// CHECK: int has_clang_likely_5;
+
+#define CL_2 clang::\
+likely
+
+#if __has_c_attribute(CL_2)
+int has_clang_likely_6;
+#endif
+// CHECK: int has_clang_likely_6;
+
+#if __has_c_attribute(CL_2\
+)
+int has_clang_likely_7;
+#endif
+// CHECK: int has_clang_likely_7;
diff --git a/clang/test/Preprocessor/has_include.c 
b/clang/test/Preprocessor/has_include.c
index c95025d83860a..ff199bf23063f 100644
--- a/clang/test/Preprocessor/has_include.c
+++ b/clang/test/Preprocessor/has_include.c
@@ -197,3 +19