|
1 | 1 | Auto generated patch. Do not edit or delete it, even if empty.
|
2 |
| -diff -ruN --strip-trailing-cr a/lldb/unittests/Core/MangledTest.cpp b/lldb/unittests/Core/MangledTest.cpp |
3 |
| ---- a/lldb/unittests/Core/MangledTest.cpp |
4 |
| -+++ b/lldb/unittests/Core/MangledTest.cpp |
5 |
| -@@ -605,6 +605,7 @@ |
6 |
| - EXPECT_EQ(get_part(OB.NameInfo.BasenameRange), basename); |
7 |
| - EXPECT_EQ(get_part(OB.NameInfo.ScopeRange), scope); |
8 |
| - EXPECT_EQ(get_part(OB.NameInfo.QualifiersRange), qualifiers); |
9 |
| -+ std::free(OB.getBuffer()); |
| 2 | +diff -ruN --strip-trailing-cr a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h |
| 3 | +--- a/clang/include/clang/AST/Type.h |
| 4 | ++++ b/clang/include/clang/AST/Type.h |
| 5 | +@@ -3602,6 +3602,9 @@ |
| 6 | + } |
| 7 | + |
| 8 | + NestedNameSpecifier *getQualifier() const { return Qualifier; } |
| 9 | ++ /// Note: this can trigger extra deserialization when external AST sources are |
| 10 | ++ /// used. Prefer `getCXXRecordDecl()` unless you really need the most recent |
| 11 | ++ /// decl. |
| 12 | + CXXRecordDecl *getMostRecentCXXRecordDecl() const; |
| 13 | + |
| 14 | + bool isSugared() const; |
| 15 | +@@ -3610,7 +3613,10 @@ |
| 16 | + } |
| 17 | + |
| 18 | + void Profile(llvm::FoldingSetNodeID &ID) { |
| 19 | +- Profile(ID, getPointeeType(), getQualifier(), getMostRecentCXXRecordDecl()); |
| 20 | ++ // FIXME: `getMostRecentCXXRecordDecl()` should be possible to use here, |
| 21 | ++ // however when external AST sources are used it causes nondeterminism |
| 22 | ++ // issues (see https://github.com/llvm/llvm-project/pull/137910). |
| 23 | ++ Profile(ID, getPointeeType(), getQualifier(), getCXXRecordDecl()); |
| 24 | + } |
| 25 | + |
| 26 | + static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee, |
| 27 | +@@ -3620,6 +3626,9 @@ |
| 28 | + static bool classof(const Type *T) { |
| 29 | + return T->getTypeClass() == MemberPointer; |
| 30 | + } |
| 31 | ++ |
| 32 | ++private: |
| 33 | ++ CXXRecordDecl *getCXXRecordDecl() const; |
| 34 | + }; |
| 35 | + |
| 36 | + /// Capture whether this is a normal array (e.g. int X[4]) |
| 37 | +diff -ruN --strip-trailing-cr a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp |
| 38 | +--- a/clang/lib/AST/Type.cpp |
| 39 | ++++ b/clang/lib/AST/Type.cpp |
| 40 | +@@ -5305,10 +5305,14 @@ |
| 41 | + ID.AddPointer(Cls->getCanonicalDecl()); |
| 42 | + } |
| 43 | + |
| 44 | ++CXXRecordDecl *MemberPointerType::getCXXRecordDecl() const { |
| 45 | ++ return dyn_cast<MemberPointerType>(getCanonicalTypeInternal()) |
| 46 | ++ ->getQualifier() |
| 47 | ++ ->getAsRecordDecl(); |
| 48 | ++} |
| 49 | ++ |
| 50 | + CXXRecordDecl *MemberPointerType::getMostRecentCXXRecordDecl() const { |
| 51 | +- auto *RD = dyn_cast<MemberPointerType>(getCanonicalTypeInternal()) |
| 52 | +- ->getQualifier() |
| 53 | +- ->getAsRecordDecl(); |
| 54 | ++ auto *RD = getCXXRecordDecl(); |
| 55 | + if (!RD) |
| 56 | + return nullptr; |
| 57 | + return RD->getMostRecentNonInjectedDecl(); |
| 58 | +diff -ruN --strip-trailing-cr a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp |
| 59 | +--- a/clang/lib/Sema/SemaChecking.cpp |
| 60 | ++++ b/clang/lib/Sema/SemaChecking.cpp |
| 61 | +@@ -11596,6 +11596,15 @@ |
| 62 | + } |
10 | 63 | }
|
11 | 64 |
|
12 |
| - INSTANTIATE_TEST_SUITE_P(DemanglingPartsTests, DemanglingPartsTestFixture, |
| 65 | ++static void CheckCommaOperand(Sema &S, Expr *E, QualType T, SourceLocation CC, |
| 66 | ++ bool ExtraCheckForImplicitConversion) { |
| 67 | ++ E = E->IgnoreParenImpCasts(); |
| 68 | ++ AnalyzeImplicitConversions(S, E, CC); |
| 69 | ++ |
| 70 | ++ if (ExtraCheckForImplicitConversion && E->getType() != T) |
| 71 | ++ S.CheckImplicitConversion(E, T, CC); |
| 72 | ++} |
| 73 | ++ |
| 74 | + /// Analyze the given compound assignment for the possible losing of |
| 75 | + /// floating-point precision. |
| 76 | + static void AnalyzeCompoundAssignment(Sema &S, BinaryOperator *E) { |
| 77 | +@@ -12413,7 +12422,7 @@ |
| 78 | + << OrigE->getSourceRange() << T->isBooleanType() |
| 79 | + << FixItHint::CreateReplacement(UO->getBeginLoc(), "!"); |
| 80 | + |
| 81 | +- if (const auto *BO = dyn_cast<BinaryOperator>(SourceExpr)) |
| 82 | ++ if (auto *BO = dyn_cast<BinaryOperator>(SourceExpr)) { |
| 83 | + if ((BO->getOpcode() == BO_And || BO->getOpcode() == BO_Or) && |
| 84 | + BO->getLHS()->isKnownToHaveBooleanValue() && |
| 85 | + BO->getRHS()->isKnownToHaveBooleanValue() && |
| 86 | +@@ -12439,7 +12448,21 @@ |
| 87 | + (BO->getOpcode() == BO_And ? "&&" : "||")); |
| 88 | + S.Diag(BO->getBeginLoc(), diag::note_cast_operand_to_int); |
| 89 | + } |
| 90 | ++ } else if (BO->isCommaOp() && !S.getLangOpts().CPlusPlus) { |
| 91 | ++ /// Analyze the given comma operator. The basic idea behind the analysis |
| 92 | ++ /// is to analyze the left and right operands slightly differently. The |
| 93 | ++ /// left operand needs to check whether the operand itself has an implicit |
| 94 | ++ /// conversion, but not whether the left operand induces an implicit |
| 95 | ++ /// conversion for the entire comma expression itself. This is similar to |
| 96 | ++ /// how CheckConditionalOperand behaves; it's as-if the correct operand |
| 97 | ++ /// were directly used for the implicit conversion check. |
| 98 | ++ CheckCommaOperand(S, BO->getLHS(), T, BO->getOperatorLoc(), |
| 99 | ++ /*ExtraCheckForImplicitConversion=*/false); |
| 100 | ++ CheckCommaOperand(S, BO->getRHS(), T, BO->getOperatorLoc(), |
| 101 | ++ /*ExtraCheckForImplicitConversion=*/true); |
| 102 | ++ return; |
| 103 | + } |
| 104 | ++ } |
| 105 | + |
| 106 | + // For conditional operators, we analyze the arguments as if they |
| 107 | + // were being fed directly into the output. |
| 108 | +diff -ruN --strip-trailing-cr a/clang/test/Sema/implicit-cast.c b/clang/test/Sema/implicit-cast.c |
| 109 | +--- a/clang/test/Sema/implicit-cast.c |
| 110 | ++++ b/clang/test/Sema/implicit-cast.c |
| 111 | +@@ -1,4 +1,4 @@ |
| 112 | +-// RUN: %clang_cc1 -fsyntax-only %s |
| 113 | ++// RUN: %clang_cc1 -fsyntax-only -verify %s |
| 114 | + |
| 115 | + static char *test1(int cf) { |
| 116 | + return cf ? "abc" : 0; |
| 117 | +@@ -6,3 +6,8 @@ |
| 118 | + static char *test2(int cf) { |
| 119 | + return cf ? 0 : "abc"; |
| 120 | + } |
| 121 | ++ |
| 122 | ++int baz(void) { |
| 123 | ++ int f; |
| 124 | ++ return ((void)0, f = 1.4f); // expected-warning {{implicit conversion from 'float' to 'int' changes value from 1.4 to 1}} |
| 125 | ++} |
| 126 | +diff -ruN --strip-trailing-cr a/clang/test/Sema/implicit-int-enum-conversion.c b/clang/test/Sema/implicit-int-enum-conversion.c |
| 127 | +--- a/clang/test/Sema/implicit-int-enum-conversion.c |
| 128 | ++++ b/clang/test/Sema/implicit-int-enum-conversion.c |
| 129 | +@@ -50,3 +50,25 @@ |
| 130 | + return E2_Zero; // expected-warning {{implicit conversion from enumeration type 'enum E2' to different enumeration type 'enum E1'}} \ |
| 131 | + cxx-error {{cannot initialize return object of type 'enum E1' with an rvalue of type 'E2'}} |
| 132 | + } |
| 133 | ++ |
| 134 | ++enum E1 comma1(void) { |
| 135 | ++ return ((void)0, E1_One); |
| 136 | ++} |
| 137 | ++ |
| 138 | ++enum E1 comma2(void) { |
| 139 | ++ enum E1 x; |
| 140 | ++ return |
| 141 | ++ (x = 12, // expected-warning {{implicit conversion from 'int' to enumeration type 'enum E1' is invalid in C++}} \ |
| 142 | ++ cxx-error {{assigning to 'enum E1' from incompatible type 'int'}} |
| 143 | ++ E1_One); |
| 144 | ++} |
| 145 | ++ |
| 146 | ++enum E1 comma3(void) { |
| 147 | ++ enum E1 x; |
| 148 | ++ return ((void)0, foo()); // Okay, no conversion in C++ |
| 149 | ++} |
| 150 | ++ |
| 151 | ++enum E1 comma4(void) { |
| 152 | ++ return ((void)1, 2); // expected-warning {{implicit conversion from 'int' to enumeration type 'enum E1' is invalid in C++}} \ |
| 153 | ++ cxx-error {{cannot initialize return object of type 'enum E1' with an rvalue of type 'int'}} |
| 154 | ++} |
0 commit comments