|
| 1 | +diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h |
| 2 | +index 9a8dd6faff..95639fcaed 100644 |
| 3 | +--- a/include/clang/AST/Type.h |
| 4 | ++++ b/include/clang/AST/Type.h |
| 5 | +@@ -3456,6 +3456,7 @@ public: |
| 6 | + IsConsumed = 0x10, |
| 7 | + HasPassObjSize = 0x20, |
| 8 | + IsNoEscape = 0x40, |
| 9 | ++ IsMayExtend = 0x80, |
| 10 | + }; |
| 11 | + unsigned char Data = 0; |
| 12 | + |
| 13 | +@@ -3509,6 +3510,19 @@ public: |
| 14 | + return Copy; |
| 15 | + } |
| 16 | + |
| 17 | ++ bool isNodeCppMayExtend() const { |
| 18 | ++ return Data & IsMayExtend; |
| 19 | ++ } |
| 20 | ++ |
| 21 | ++ ExtParameterInfo withNodeCppMayExtend(bool MayExtend) const { |
| 22 | ++ ExtParameterInfo Copy = *this; |
| 23 | ++ if (MayExtend) |
| 24 | ++ Copy.Data |= IsMayExtend; |
| 25 | ++ else |
| 26 | ++ Copy.Data &= ~IsMayExtend; |
| 27 | ++ return Copy; |
| 28 | ++ } |
| 29 | ++ |
| 30 | + unsigned char getOpaqueValue() const { return Data; } |
| 31 | + static ExtParameterInfo getFromOpaqueValue(unsigned char data) { |
| 32 | + ExtParameterInfo result; |
| 33 | +diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td |
| 34 | +index 1f17819dba..e1ca7b0e52 100644 |
| 35 | +--- a/include/clang/Basic/Attr.td |
| 36 | ++++ b/include/clang/Basic/Attr.td |
| 37 | +@@ -2971,3 +2971,21 @@ def InternalLinkage : InheritableAttr { |
| 38 | + let Subjects = SubjectList<[Var, Function, CXXRecord]>; |
| 39 | + let Documentation = [InternalLinkageDocs]; |
| 40 | + } |
| 41 | ++ |
| 42 | ++def NodeCppNakedStruct : InheritableAttr { |
| 43 | ++ let Spellings = [CXX11<"nodecpp","naked_struct">]; |
| 44 | ++ let Subjects = SubjectList<[CXXRecord]>; |
| 45 | ++ let Documentation = [NodeCppNoInstanceDocs]; |
| 46 | ++} |
| 47 | ++ |
| 48 | ++def NodeCppMayExtend : InheritableAttr { |
| 49 | ++ let Spellings = [CXX11<"nodecpp","may_extend_to_this">]; |
| 50 | ++ let Subjects = SubjectList<[ParmVar]>; |
| 51 | ++ let Documentation = [NodeCppMayExtendDocs]; |
| 52 | ++} |
| 53 | ++ |
| 54 | ++def NodeCppOwnedByThis : InheritableAttr { |
| 55 | ++ let Spellings = [CXX11<"nodecpp","owned_by_this">]; |
| 56 | ++ let Subjects = SubjectList<[ParmVar]>; |
| 57 | ++ let Documentation = [NodeCppMayExtendDocs]; |
| 58 | ++} |
| 59 | +diff --git a/include/clang/Basic/AttrDocs.td b/include/clang/Basic/AttrDocs.td |
| 60 | +index bb2993eab4..c06c3ac224 100644 |
| 61 | +--- a/include/clang/Basic/AttrDocs.td |
| 62 | ++++ b/include/clang/Basic/AttrDocs.td |
| 63 | +@@ -3458,3 +3458,27 @@ the resulting instructions with the call site, rather than with the |
| 64 | + corresponding line within the inlined callee. |
| 65 | + }]; |
| 66 | + } |
| 67 | ++def DocCatNodeCpp : DocumentationCategory<"Node-dot-cpp specifics"> { |
| 68 | ++ let Content = [{ |
| 69 | ++Node-dot-cpp specific attributes |
| 70 | ++ }]; |
| 71 | ++} |
| 72 | ++ |
| 73 | ++ |
| 74 | ++def NodeCppNoInstanceDocs : Documentation { |
| 75 | ++ let Category = DocCatNodeCpp; |
| 76 | ++ let Content = [{ |
| 77 | ++This attribute is used on class / struct declaration to indicate that safe code |
| 78 | ++shouldn't be allowed to create instances of it. |
| 79 | ++All instances are created by infraestructure only. |
| 80 | ++}]; |
| 81 | ++} |
| 82 | ++ |
| 83 | ++def NodeCppMayExtendDocs : Documentation { |
| 84 | ++ let Category = DocCatNodeCpp; |
| 85 | ++ let Content = [{ |
| 86 | ++This attribute is used on parameter declaration to indicate that lifetime |
| 87 | ++of naked pointer arguments may be extended inside the function. |
| 88 | ++Checker must add extra validations to such arguments. |
| 89 | ++}]; |
| 90 | ++} |
| 91 | +diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp |
| 92 | +index e032c312aa..6db41bea0a 100644 |
| 93 | +--- a/lib/AST/TypePrinter.cpp |
| 94 | ++++ b/lib/AST/TypePrinter.cpp |
| 95 | +@@ -778,6 +778,8 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T, |
| 96 | + if (EPI.isConsumed()) OS << "__attribute__((ns_consumed)) "; |
| 97 | + if (EPI.isNoEscape()) |
| 98 | + OS << "__attribute__((noescape)) "; |
| 99 | ++ if (EPI.isNodeCppMayExtend()) |
| 100 | ++ OS << "[[nodecpp::may_extend_to_this]] "; |
| 101 | + auto ABI = EPI.getABI(); |
| 102 | + if (ABI != ParameterABI::Ordinary) |
| 103 | + OS << "__attribute__((" << getParameterABISpelling(ABI) << ")) "; |
| 104 | +diff --git a/lib/ASTMatchers/ASTMatchFinder.cpp b/lib/ASTMatchers/ASTMatchFinder.cpp |
| 105 | +index 63f8395b82..3247693879 100644 |
| 106 | +--- a/lib/ASTMatchers/ASTMatchFinder.cpp |
| 107 | ++++ b/lib/ASTMatchers/ASTMatchFinder.cpp |
| 108 | +@@ -842,6 +842,20 @@ bool MatchASTVisitor::TraverseDecl(Decl *DeclNode) { |
| 109 | + if (!DeclNode) { |
| 110 | + return true; |
| 111 | + } |
| 112 | ++ |
| 113 | ++ //mb: we don't traverse decls in system-headers |
| 114 | ++ if (!isa<TranslationUnitDecl>(DeclNode)) { |
| 115 | ++ |
| 116 | ++ auto &SourceManager = getASTContext().getSourceManager(); |
| 117 | ++ auto ExpansionLoc = SourceManager.getExpansionLoc(DeclNode->getLocStart()); |
| 118 | ++ if (ExpansionLoc.isInvalid()) { |
| 119 | ++ return true; |
| 120 | ++ } |
| 121 | ++ if (SourceManager.isInSystemHeader(ExpansionLoc)) { |
| 122 | ++ return true; |
| 123 | ++ } |
| 124 | ++ } |
| 125 | ++ |
| 126 | + match(*DeclNode); |
| 127 | + return RecursiveASTVisitor<MatchASTVisitor>::TraverseDecl(DeclNode); |
| 128 | + } |
| 129 | +diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp |
| 130 | +index 77deed6047..251205865e 100644 |
| 131 | +--- a/lib/Sema/SemaDeclAttr.cpp |
| 132 | ++++ b/lib/Sema/SemaDeclAttr.cpp |
| 133 | +@@ -6604,6 +6604,16 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, |
| 134 | + case ParsedAttr::AT_XRayLogArgs: |
| 135 | + handleXRayLogArgsAttr(S, D, AL); |
| 136 | + break; |
| 137 | ++ case ParsedAttr::AT_NodeCppNakedStruct: |
| 138 | ++ handleSimpleAttribute<NodeCppNakedStructAttr>(S, D, AL); |
| 139 | ++ break; |
| 140 | ++ case ParsedAttr::AT_NodeCppMayExtend: |
| 141 | ++ handleSimpleAttribute<NodeCppMayExtendAttr>(S, D, AL); |
| 142 | ++ break; |
| 143 | ++ case ParsedAttr::AT_NodeCppOwnedByThis: |
| 144 | ++ handleSimpleAttribute<NodeCppOwnedByThisAttr>(S, D, AL); |
| 145 | ++ break; |
| 146 | ++ |
| 147 | + } |
| 148 | + } |
| 149 | + |
| 150 | +diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp |
| 151 | +index 4cf3abdf57..e0d60f63c9 100644 |
| 152 | +--- a/lib/Sema/SemaDeclCXX.cpp |
| 153 | ++++ b/lib/Sema/SemaDeclCXX.cpp |
| 154 | +@@ -14551,8 +14551,8 @@ bool Sema::CheckOverridingFunctionAttributes(const CXXMethodDecl *New, |
| 155 | + const auto *NewFT = New->getType()->getAs<FunctionProtoType>(); |
| 156 | + const auto *OldFT = Old->getType()->getAs<FunctionProtoType>(); |
| 157 | + |
| 158 | +- if (OldFT->hasExtParameterInfos()) { |
| 159 | +- for (unsigned I = 0, E = OldFT->getNumParams(); I != E; ++I) |
| 160 | ++ if (OldFT->hasExtParameterInfos() || NewFT->hasExtParameterInfos()) { |
| 161 | ++ for (unsigned I = 0, E = OldFT->getNumParams(); I != E; ++I) { |
| 162 | + // A parameter of the overriding method should be annotated with noescape |
| 163 | + // if the corresponding parameter of the overridden method is annotated. |
| 164 | + if (OldFT->getExtParameterInfo(I).isNoEscape() && |
| 165 | +@@ -14562,6 +14562,18 @@ bool Sema::CheckOverridingFunctionAttributes(const CXXMethodDecl *New, |
| 166 | + Diag(Old->getParamDecl(I)->getLocation(), |
| 167 | + diag::note_overridden_marked_noescape); |
| 168 | + } |
| 169 | ++ |
| 170 | ++ if (!OldFT->getExtParameterInfo(I).isNodeCppMayExtend() && |
| 171 | ++ NewFT->getExtParameterInfo(I).isNodeCppMayExtend()) { |
| 172 | ++ Diag(New->getParamDecl(I)->getLocation(), |
| 173 | ++ diag::err_conflicting_overriding_cc_attributes) |
| 174 | ++ << New->getDeclName() << New->getType() << Old->getType(); |
| 175 | ++ Diag(Old->getParamDecl(I)->getLocation(), |
| 176 | ++ diag::note_overridden_virtual_function); |
| 177 | ++ |
| 178 | ++ return true; |
| 179 | ++ } |
| 180 | ++ } |
| 181 | + } |
| 182 | + |
| 183 | + // Virtual overrides must have the same code_seg. |
| 184 | +diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp |
| 185 | +index 284d34b22c..6903dba961 100644 |
| 186 | +--- a/lib/Sema/SemaType.cpp |
| 187 | ++++ b/lib/Sema/SemaType.cpp |
| 188 | +@@ -4690,6 +4690,11 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, |
| 189 | + HasAnyInterestingExtParameterInfos = true; |
| 190 | + } |
| 191 | + |
| 192 | ++ if (Param->hasAttr<NodeCppMayExtendAttr>()) { |
| 193 | ++ ExtParameterInfos[i] = ExtParameterInfos[i].withNodeCppMayExtend(true); |
| 194 | ++ HasAnyInterestingExtParameterInfos = true; |
| 195 | ++ } |
| 196 | ++ |
| 197 | + ParamTys.push_back(ParamTy); |
| 198 | + } |
| 199 | + |
| 200 | +diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt |
| 201 | +index 9f76d36dba..105215e3a5 100644 |
| 202 | +--- a/tools/CMakeLists.txt |
| 203 | ++++ b/tools/CMakeLists.txt |
| 204 | +@@ -35,3 +35,6 @@ add_llvm_external_project(clang-tools-extra extra) |
| 205 | + |
| 206 | + # libclang may require clang-tidy in clang-tools-extra. |
| 207 | + add_clang_subdirectory(libclang) |
| 208 | ++ |
| 209 | ++# Add nodecpp here, because using LLVM_EXTERNAL_PROJECTS don't seem to work |
| 210 | ++add_llvm_external_project(checker) |
0 commit comments