[llvm-branch-commits] [clang] 68f5396 - [ASTImporter] Fix import of a typedef that has an attribute
Author: Gabor Marton Date: 2020-12-14T18:27:05+01:00 New Revision: 68f53960e17d93c3a2727164dac4e54140bd98ba URL: https://github.com/llvm/llvm-project/commit/68f53960e17d93c3a2727164dac4e54140bd98ba DIFF: https://github.com/llvm/llvm-project/commit/68f53960e17d93c3a2727164dac4e54140bd98ba.diff LOG: [ASTImporter] Fix import of a typedef that has an attribute The import of a typedefs with an attribute uses clang::Decl::setAttrs(). But that needs the ASTContext which we can get only from the TranslationUnitDecl. But we can get the TUDecl only thourgh the DeclContext, which is not set by the time of the setAttrs call. Fix: import the attributes only after the DC is surely imported. Btw, having the attribute import initiated from GetImportedOrCreateDecl was fundamentally flawed. Now that is implicitly fixed. Differential Revision: https://reviews.llvm.org/D92962 Added: Modified: clang/lib/AST/ASTImporter.cpp clang/unittests/AST/ASTImporterTest.cpp Removed: diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index ea05f2ea4552..10fa6990624d 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -264,16 +264,6 @@ namespace clang { void InitializeImportedDecl(Decl *FromD, Decl *ToD) { ToD->IdentifierNamespace = FromD->IdentifierNamespace; - if (FromD->hasAttrs()) -for (const Attr *FromAttr : FromD->getAttrs()) { - // FIXME: Return of the error here is not possible until store of - // import errors is implemented. - auto ToAttrOrErr = import(FromAttr); - if (ToAttrOrErr) -ToD->addAttr(*ToAttrOrErr); - else -llvm::consumeError(ToAttrOrErr.takeError()); -} if (FromD->isUsed()) ToD->setIsUsed(); if (FromD->isImplicit()) @@ -8328,6 +8318,15 @@ Expected ASTImporter::Import(Decl *FromD) { // Make sure that ImportImpl registered the imported decl. assert(ImportedDecls.count(FromD) != 0 && "Missing call to MapImported?"); + if (FromD->hasAttrs()) +for (const Attr *FromAttr : FromD->getAttrs()) { + auto ToAttrOrErr = Import(FromAttr); + if (ToAttrOrErr) +ToD->addAttr(*ToAttrOrErr); + else +return ToAttrOrErr.takeError(); +} + // Notify subclasses. Imported(FromD, ToD); diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index e81e5d028cd0..40340cb6f9bc 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -6084,6 +6084,24 @@ TEST_P(CTAD, DeductionGuideShouldCopyALocalTypedef) { INSTANTIATE_TEST_CASE_P(ParameterizedTests, CTAD, DefaultTestValuesForRunOptions, ); +TEST_P(ASTImporterOptionSpecificTestBase, TypedefWithAttribute) { + Decl *TU = getTuDecl( + R"( + namespace N { +typedef int X __attribute__((annotate("A"))); + } + )", + Lang_CXX17, "input.cc"); + auto *FromD = + FirstDeclMatcher().match(TU, typedefDecl(hasName("X"))); + auto *ToD = Import(FromD, Lang_CXX17); + ASSERT_TRUE(ToD); + ASSERT_EQ(ToD->getAttrs().size(), 1); + auto *ToAttr = dyn_cast(ToD->getAttrs()[0]); + ASSERT_TRUE(ToAttr); + EXPECT_EQ(ToAttr->getAnnotation(), "A"); +} + INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest, DefaultTestValuesForRunOptions, ); ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] f1ca50a - D88665 id 295585 [ASTImporter][AST] Fix structural equivalency crash on dependent FieldDecl
Author: Gabor Marton Date: 2020-10-14T11:15:06+02:00 New Revision: f1ca50a5094653463e350daa6c508885f61f11b4 URL: https://github.com/llvm/llvm-project/commit/f1ca50a5094653463e350daa6c508885f61f11b4 DIFF: https://github.com/llvm/llvm-project/commit/f1ca50a5094653463e350daa6c508885f61f11b4.diff LOG: D88665 id 295585 [ASTImporter][AST] Fix structural equivalency crash on dependent FieldDecl Added: Modified: clang/lib/AST/ASTStructuralEquivalence.cpp clang/unittests/AST/StructuralEquivalenceTest.cpp Removed: diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index 8b5b2444f1e2..3dcd4159dc0b 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -1071,6 +1071,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, } if (Field1->isBitField()) { +bool isVD1 = Field1->getBitWidth()->isValueDependent(); +bool isVD2 = Field2->getBitWidth()->isValueDependent(); +if (isVD1 || isVD2) + return isVD1 && isVD2; // Make sure that the bit-fields are the same length. unsigned Bits1 = Field1->getBitWidthValue(Context.FromCtx); unsigned Bits2 = Field2->getBitWidthValue(Context.ToCtx); diff --git a/clang/unittests/AST/StructuralEquivalenceTest.cpp b/clang/unittests/AST/StructuralEquivalenceTest.cpp index 2b5ce0fed51d..b5aff49eaaee 100644 --- a/clang/unittests/AST/StructuralEquivalenceTest.cpp +++ b/clang/unittests/AST/StructuralEquivalenceTest.cpp @@ -906,6 +906,12 @@ TEST_F(StructuralEquivalenceTemplateTest, DifferentTemplateArgKind) { EXPECT_FALSE(testStructuralMatch(t)); } +TEST_F(StructuralEquivalenceTemplateTest, DependentFieldDecl) { + const char *Code = "template class foo { int a : sizeof(T); };"; + auto t = makeNamedDecls(Code, Code, Lang_CXX03); + EXPECT_TRUE(testStructuralMatch(t)); +} + TEST_F(StructuralEquivalenceTemplateTest, ExplicitBoolSame) { auto Decls = makeNamedDecls( "template struct foo {explicit(b) foo(int);};", ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] c7203d1 - [analyzer] Fix crash with pointer to members values
Author: Valeriy Savchenko Date: 2020-10-14T11:15:06+02:00 New Revision: c7203d1457dd206b48780d8e3a786b2c1b91b4f0 URL: https://github.com/llvm/llvm-project/commit/c7203d1457dd206b48780d8e3a786b2c1b91b4f0 DIFF: https://github.com/llvm/llvm-project/commit/c7203d1457dd206b48780d8e3a786b2c1b91b4f0.diff LOG: [analyzer] Fix crash with pointer to members values This fix unifies all of the different ways we handled pointer to members into one. The crash was caused by the fact that the type of pointer-to-member values was `void *`, and while this works for the vast majority of cases it breaks when we actually need to explain the path for the report. rdar://problem/64202361 Differential Revision: https://reviews.llvm.org/D85817 Added: clang/test/Analysis/PR46264.cpp Modified: clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp clang/lib/StaticAnalyzer/Core/ExprEngine.cpp clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp clang/lib/StaticAnalyzer/Core/SValBuilder.cpp clang/lib/StaticAnalyzer/Core/SVals.cpp clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp clang/test/Analysis/pointer-to-member.cpp Removed: diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h index a001c0dc7030..142b1ab11750 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h @@ -79,11 +79,11 @@ class LazyCompoundValData : public llvm::FoldingSetNode { }; class PointerToMemberData : public llvm::FoldingSetNode { - const DeclaratorDecl *D; + const NamedDecl *D; llvm::ImmutableList L; public: - PointerToMemberData(const DeclaratorDecl *D, + PointerToMemberData(const NamedDecl *D, llvm::ImmutableList L) : D(D), L(L) {} @@ -92,11 +92,11 @@ class PointerToMemberData : public llvm::FoldingSetNode { iterator begin() const { return L.begin(); } iterator end() const { return L.end(); } - static void Profile(llvm::FoldingSetNodeID& ID, const DeclaratorDecl *D, + static void Profile(llvm::FoldingSetNodeID &ID, const NamedDecl *D, llvm::ImmutableList L); - void Profile(llvm::FoldingSetNodeID& ID) { Profile(ID, D, L); } - const DeclaratorDecl *getDeclaratorDecl() const {return D;} + void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, D, L); } + const NamedDecl *getDeclaratorDecl() const { return D; } llvm::ImmutableList getCXXBaseList() const { return L; @@ -236,9 +236,9 @@ class BasicValueFactory { const LazyCompoundValData *getLazyCompoundValData(const StoreRef &store, const TypedValueRegion *region); - const PointerToMemberData *getPointerToMemberData( - const DeclaratorDecl *DD, - llvm::ImmutableList L); + const PointerToMemberData * + getPointerToMemberData(const NamedDecl *ND, + llvm::ImmutableList L); llvm::ImmutableList getEmptySValList() { return SValListFactory.getEmptyList(); diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h index 35ebefdc00d6..4ea85f9730bb 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h @@ -233,7 +233,7 @@ class SValBuilder { const LocationContext *LCtx, unsigned count); - DefinedSVal getMemberPointer(const DeclaratorDecl *DD); + DefinedSVal getMemberPointer(const NamedDecl *ND); DefinedSVal getFunctionPointer(const FunctionDecl *func); diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index 1abe29782088..c7fc23c47a30 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -526,7 +526,7 @@ class PointerToMember : public NonLoc { public: using PTMDataType = - llvm::PointerUnion; + llvm::PointerUnion; const PTMDataType getPTMData() const { return PTMDataType::getFromOpaqueValue(const_cast(Data)); @@ -534,7 +534,7 @@ class PointerToMember : public NonLoc { bool isNullMemberPointer() const; - const DeclaratorDecl *getDecl() const; + const NamedDecl *getDecl() const; template const AdjustedDecl *getDeclAs() const { diff --git a/clang/lib/StaticAnalyzer/Core/BasicValueFactory
[llvm-branch-commits] [clang] 46a1198 - [ASTImporter] Add Visitor for TypedefNameDecl's
Author: Vince Bridgers Date: 2020-10-14T11:15:06+02:00 New Revision: 46a1198f805c65fe3f6b1170ad012819e158c1fe URL: https://github.com/llvm/llvm-project/commit/46a1198f805c65fe3f6b1170ad012819e158c1fe DIFF: https://github.com/llvm/llvm-project/commit/46a1198f805c65fe3f6b1170ad012819e158c1fe.diff LOG: [ASTImporter] Add Visitor for TypedefNameDecl's We found a case where Typedef Name Declarations were not being added correctly when importing builtin types. This exposed the need for a TypedefNameDecl visitor so these types can be added by RecordDecl and fields. This code is covered by the ASTImporterTest cases that use the implicit struct __NSConstantString_tag definitions. Thanks to @martong for the debugging assist! Depends on D83970. Reviewed By: martong Differential Revision: https://reviews.llvm.org/D83992 Added: clang/test/Analysis/Inputs/ctu-import.c clang/test/Analysis/Inputs/ctu-import.c.externalDefMap.ast-dump.txt clang/test/Analysis/ctu-implicit.c Modified: clang/lib/AST/ASTImporterLookupTable.cpp Removed: diff --git a/clang/lib/AST/ASTImporterLookupTable.cpp b/clang/lib/AST/ASTImporterLookupTable.cpp index 4d6fff8f3419..e17d6082dcdc 100644 --- a/clang/lib/AST/ASTImporterLookupTable.cpp +++ b/clang/lib/AST/ASTImporterLookupTable.cpp @@ -22,6 +22,20 @@ namespace { struct Builder : RecursiveASTVisitor { ASTImporterLookupTable < Builder(ASTImporterLookupTable <) : LT(LT) {} + + bool VisitTypedefNameDecl(TypedefNameDecl *D) { +QualType Ty = D->getUnderlyingType(); +Ty = Ty.getCanonicalType(); +if (const auto *RTy = dyn_cast(Ty)) { + LT.add(RTy->getAsRecordDecl()); + // iterate over the field decls, adding them + for (auto *it : RTy->getAsRecordDecl()->fields()) { +LT.add(it); + } +} +return true; + } + bool VisitNamedDecl(NamedDecl *D) { LT.add(D); return true; diff --git a/clang/test/Analysis/Inputs/ctu-import.c b/clang/test/Analysis/Inputs/ctu-import.c new file mode 100644 index ..6c99a3642797 --- /dev/null +++ b/clang/test/Analysis/Inputs/ctu-import.c @@ -0,0 +1,15 @@ + +// Use an internal, implicitly defined type, called by +// a function imported for CTU. This should not crash. +int foo(void); +int foobar(int skip) { + __NSConstantString str = {.flags = 1}; + + if (str.flags >= 0) +str.flags = 0; + return 4; +} + +int testStaticImplicit(void) { + return foobar(3); +} diff --git a/clang/test/Analysis/Inputs/ctu-import.c.externalDefMap.ast-dump.txt b/clang/test/Analysis/Inputs/ctu-import.c.externalDefMap.ast-dump.txt new file mode 100644 index ..83d3b4ca451e --- /dev/null +++ b/clang/test/Analysis/Inputs/ctu-import.c.externalDefMap.ast-dump.txt @@ -0,0 +1 @@ +c:@F@testStaticImplicit ctu-import.c.ast diff --git a/clang/test/Analysis/ctu-implicit.c b/clang/test/Analysis/ctu-implicit.c new file mode 100644 index ..925044845e09 --- /dev/null +++ b/clang/test/Analysis/ctu-implicit.c @@ -0,0 +1,20 @@ +// RUN: rm -rf %t && mkdir %t +// RUN: mkdir -p %t/ctudir2 +// RUN: %clang_cc1 \ +// RUN: -emit-pch -o %t/ctudir2/ctu-import.c.ast %S/Inputs/ctu-import.c +// RUN: cp %S/Inputs/ctu-import.c.externalDefMap.ast-dump.txt %t/ctudir2/externalDefMap.txt +// RUN: %clang_cc1 -analyze \ +// RUN: -analyzer-checker=core,debug.ExprInspection \ +// RUN: -analyzer-config experimental-enable-naive-ctu-analysis=true \ +// RUN: -analyzer-config display-ctu-progress=true \ +// RUN: -analyzer-config ctu-dir=%t/ctudir2 \ +// RUN: -verify %s + +void clang_analyzer_eval(int); + +int testStaticImplicit(void); +int func(void) { + int ret = testStaticImplicit(); + clang_analyzer_eval(ret == 4); // expected-warning{{TRUE}} + return testStaticImplicit(); +} ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] 70eb2ce - [ASTImporter] Support import of CXXDeductionGuideDecl
Author: Gabor Marton Date: 2020-11-30T17:55:25+01:00 New Revision: 70eb2ce395be1fe39ceede6719aa667658d1e5a3 URL: https://github.com/llvm/llvm-project/commit/70eb2ce395be1fe39ceede6719aa667658d1e5a3 DIFF: https://github.com/llvm/llvm-project/commit/70eb2ce395be1fe39ceede6719aa667658d1e5a3.diff LOG: [ASTImporter] Support import of CXXDeductionGuideDecl CXXDeductionGuideDecl is a FunctionDecl, but its constructor should be called appropriately, at least to set the kind variable properly. Differential Revision: https://reviews.llvm.org/D92109 Added: Modified: clang/lib/AST/ASTImporter.cpp clang/unittests/AST/ASTImporterTest.cpp Removed: diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 01ee8d275af1..1b014314996b 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -499,6 +499,7 @@ namespace clang { ExpectedDecl VisitCXXConstructorDecl(CXXConstructorDecl *D); ExpectedDecl VisitCXXDestructorDecl(CXXDestructorDecl *D); ExpectedDecl VisitCXXConversionDecl(CXXConversionDecl *D); +ExpectedDecl VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D); ExpectedDecl VisitFieldDecl(FieldDecl *D); ExpectedDecl VisitIndirectFieldDecl(IndirectFieldDecl *D); ExpectedDecl VisitFriendDecl(FriendDecl *D); @@ -3328,6 +3329,17 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { return ToPOrErr.takeError(); } + // Common code to import an explicit specifier of diff erent kind of functions. + auto ImportExplicitExpr = [this, &Err](auto *Fun) -> ExpectedExpr { +Expr *ExplicitExpr = nullptr; +if (Fun->getExplicitSpecifier().getExpr()) { + ExplicitExpr = importChecked(Err, Fun->getExplicitSpecifier().getExpr()); + if (Err) +return std::move(Err); +} +return ExplicitExpr; + }; + // Create the imported function. FunctionDecl *ToFunction = nullptr; if (auto *FromConstructor = dyn_cast(D)) { @@ -3369,17 +3381,13 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { ToDtor->setOperatorDelete(ToOperatorDelete, ToThisArg); } else if (CXXConversionDecl *FromConversion = dyn_cast(D)) { -Expr *ExplicitExpr = nullptr; -if (FromConversion->getExplicitSpecifier().getExpr()) { - auto Imp = import(FromConversion->getExplicitSpecifier().getExpr()); - if (!Imp) -return Imp.takeError(); - ExplicitExpr = *Imp; -} +ExpectedExpr ExplicitExpr = ImportExplicitExpr(FromConversion); +if (!ExplicitExpr) + return ExplicitExpr.takeError(); if (GetImportedOrCreateDecl( ToFunction, D, Importer.getToContext(), cast(DC), ToInnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(), -ExplicitSpecifier(ExplicitExpr, +ExplicitSpecifier(*ExplicitExpr, FromConversion->getExplicitSpecifier().getKind()), D->getConstexprKind(), SourceLocation(), TrailingRequiresClause)) return ToFunction; @@ -3390,6 +3398,18 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { Method->isInlineSpecified(), D->getConstexprKind(), SourceLocation(), TrailingRequiresClause)) return ToFunction; + } else if (auto *Guide = dyn_cast(D)) { +ExpectedExpr ExplicitExpr = ImportExplicitExpr(Guide); +if (!ExplicitExpr) + return ExplicitExpr.takeError(); +if (GetImportedOrCreateDecl( +ToFunction, D, Importer.getToContext(), DC, ToInnerLocStart, +ExplicitSpecifier(*ExplicitExpr, + Guide->getExplicitSpecifier().getKind()), +NameInfo, T, TInfo, ToEndLoc)) + return ToFunction; +cast(ToFunction) +->setIsCopyDeductionCandidate(Guide->isCopyDeductionCandidate()); } else { if (GetImportedOrCreateDecl( ToFunction, D, Importer.getToContext(), DC, ToInnerLocStart, @@ -3517,6 +3537,11 @@ ExpectedDecl ASTNodeImporter::VisitCXXConversionDecl(CXXConversionDecl *D) { return VisitCXXMethodDecl(D); } +ExpectedDecl +ASTNodeImporter::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) { + return VisitFunctionDecl(D); +} + ExpectedDecl ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { // Import the major distinguishing characteristics of a variable. DeclContext *DC, *LexicalDC; diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index 81a92a10f48d..7e56b3ed501f 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -5957,6 +5957,47 @@ TEST_P(ImportWithExternalSource, CompleteRecordBeforeImporting) { EXPECT_EQ(Record, CompletedTags.front()); } +TEST_P(ImportFunctions, CTADImplicit) { + Decl *FromTU = getTuDecl( + R"( + template struct A { +A(T); + };
[llvm-branch-commits] [clang] b40b319 - [analyzer][StdLibraryFunctionsChecker] Add return value constraint to functions with BufferSize
Author: Gabor Marton Date: 2020-12-02T17:54:48+01:00 New Revision: b40b3196b32110f00b7610851f4ef182ac751ba0 URL: https://github.com/llvm/llvm-project/commit/b40b3196b32110f00b7610851f4ef182ac751ba0 DIFF: https://github.com/llvm/llvm-project/commit/b40b3196b32110f00b7610851f4ef182ac751ba0.diff LOG: [analyzer][StdLibraryFunctionsChecker] Add return value constraint to functions with BufferSize Differential Revision: https://reviews.llvm.org/D92474 Added: Modified: clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp Removed: diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp index f8eafde3218d..8a34950ce734 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp @@ -457,6 +457,10 @@ class StdLibraryFunctionsChecker CaseConstraints.push_back(std::move(CS)); return *this; } +Summary &Case(const ConstraintSet &CS) { + CaseConstraints.push_back(CS); + return *this; +} Summary &ArgConstraint(ValueConstraintPtr VC) { assert(VC->getArgNo() != Ret && "Arg constraint should not refer to the return value"); @@ -1235,9 +1239,8 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( // read()-like functions that never return more than buffer size. auto FreadSummary = Summary(NoEvalCall) - .Case({ - ReturnValueCondition(LessThanOrEq, ArgNo(2)), - }) + .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)), + ReturnValueCondition(WithinRange, Range(0, SizeMax))}) .ArgConstraint(NotNull(ArgNo(0))) .ArgConstraint(NotNull(ArgNo(3))) .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(0), /*BufSize=*/ArgNo(1), @@ -1764,6 +1767,8 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( Signature(ArgTypes{ConstCharPtrRestrictTy, CharPtrRestrictTy, SizeTy}, RetType{Ssize_tTy}), Summary(NoEvalCall) +.Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)), + ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))}) .ArgConstraint(NotNull(ArgNo(0))) .ArgConstraint(NotNull(ArgNo(1))) .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1), @@ -1779,6 +1784,8 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( ArgTypes{IntTy, ConstCharPtrRestrictTy, CharPtrRestrictTy, SizeTy}, RetType{Ssize_tTy}), Summary(NoEvalCall) +.Case({ReturnValueCondition(LessThanOrEq, ArgNo(3)), + ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))}) .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))) .ArgConstraint(NotNull(ArgNo(1))) .ArgConstraint(NotNull(ArgNo(2))) @@ -1842,6 +1849,9 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( Optional Socklen_tPtrRestrictTy = getRestrictTy(Socklen_tPtrTy); Optional Socklen_tMax = getMaxValue(Socklen_tTy); +const auto ReturnsZeroOrMinusOne = +ConstraintSet{ReturnValueCondition(WithinRange, Range(-1, 0))}; + // In 'socket.h' of some libc implementations with C99, sockaddr parameter // is a transparent union of the underlying sockaddr_ family of pointers // instead of being a pointer to struct sockaddr. In these cases, the @@ -1850,6 +1860,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( // constraints which require pointer types for the sockaddr param. auto Accept = Summary(NoEvalCall) +.Case({ReturnValueCondition(WithinRange, Range(-1, IntMax))}) .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))); if (!addToFunctionSummaryMap( "accept", @@ -1872,6 +1883,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( Signature(ArgTypes{IntTy, ConstStructSockaddrPtrTy, Socklen_tTy}, RetType{IntTy}), Summary(NoEvalCall) +.Case(ReturnsZeroOrMinusOne) .ArgConstraint( ArgumentCondition(0, WithinRange, Range(0, IntMax))) .ArgConstraint(NotNull(ArgNo(1))) @@ -1884,6 +1896,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( "bind", Signature(ArgTypes{IntTy, Irrelevant, Socklen_tTy}, RetType{IntTy}), Summary(NoEvalCall) + .Case(ReturnsZeroOrMinusOne) .ArgConstraint( ArgumentCondition(0, WithinRange, Range(0, IntMax))) .ArgConstraint( @@ -1897,6 +1910,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( Socklen_tPtrRestrictTy}, Ret
[llvm-branch-commits] [clang] 1e14588 - [Clang][Sema] Attempt to fix CTAD faulty copy of non-local typedefs
Author: Gabor Marton Date: 2020-12-03T11:35:47+01:00 New Revision: 1e14588d0f6845976e774c87a18a84a0f7b61015 URL: https://github.com/llvm/llvm-project/commit/1e14588d0f6845976e774c87a18a84a0f7b61015 DIFF: https://github.com/llvm/llvm-project/commit/1e14588d0f6845976e774c87a18a84a0f7b61015.diff LOG: [Clang][Sema] Attempt to fix CTAD faulty copy of non-local typedefs http://lists.llvm.org/pipermail/cfe-dev/2020-November/067252.html Differential Revision: https://reviews.llvm.org/D92101 Added: Modified: clang/lib/Sema/SemaTemplate.cpp clang/unittests/AST/ASTImporterTest.cpp Removed: diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 5b321bb74400..5710f9e3daad 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2077,27 +2077,28 @@ class ExtractTypeForDeductionGuide QualType TransformTypedefType(TypeLocBuilder &TLB, TypedefTypeLoc TL) { ASTContext &Context = SemaRef.getASTContext(); TypedefNameDecl *OrigDecl = TL.getTypedefNameDecl(); -TypeLocBuilder InnerTLB; -QualType Transformed = -TransformType(InnerTLB, OrigDecl->getTypeSourceInfo()->getTypeLoc()); -TypeSourceInfo *TSI = -TransformType(InnerTLB.getTypeSourceInfo(Context, Transformed)); - -TypedefNameDecl *Decl = nullptr; - -if (isa(OrigDecl)) - Decl = TypeAliasDecl::Create( - Context, Context.getTranslationUnitDecl(), OrigDecl->getBeginLoc(), - OrigDecl->getLocation(), OrigDecl->getIdentifier(), TSI); -else { - assert(isa(OrigDecl) && "Not a Type alias or typedef"); - Decl = TypedefDecl::Create( - Context, Context.getTranslationUnitDecl(), OrigDecl->getBeginLoc(), - OrigDecl->getLocation(), OrigDecl->getIdentifier(), TSI); +TypedefNameDecl *Decl = OrigDecl; +// Transform the underlying type of the typedef and clone the Decl only if +// the typedef has a dependent context. +if (OrigDecl->getDeclContext()->isDependentContext()) { + TypeLocBuilder InnerTLB; + QualType Transformed = + TransformType(InnerTLB, OrigDecl->getTypeSourceInfo()->getTypeLoc()); + TypeSourceInfo *TSI = + TransformType(InnerTLB.getTypeSourceInfo(Context, Transformed)); + if (isa(OrigDecl)) +Decl = TypeAliasDecl::Create( +Context, Context.getTranslationUnitDecl(), OrigDecl->getBeginLoc(), +OrigDecl->getLocation(), OrigDecl->getIdentifier(), TSI); + else { +assert(isa(OrigDecl) && "Not a Type alias or typedef"); +Decl = TypedefDecl::Create( +Context, Context.getTranslationUnitDecl(), OrigDecl->getBeginLoc(), +OrigDecl->getLocation(), OrigDecl->getIdentifier(), TSI); + } + MaterializedTypedefs.push_back(Decl); } -MaterializedTypedefs.push_back(Decl); - QualType TDTy = Context.getTypedefType(Decl); TypedefTypeLoc TypedefTL = TLB.push(TDTy); TypedefTL.setNameLoc(TL.getNameLoc()); diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index 7e56b3ed501f..e4c73a832a14 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -5998,6 +5998,77 @@ TEST_P(ImportFunctions, CTADUserDefinedExplicit) { EXPECT_TRUE(ToD->isExplicit()); } +// FIXME Move these tests out of ASTImporterTest. For that we need to factor +// out the ASTImporter specific pars from ASTImporterOptionSpecificTestBase +// into a new test Fixture. Then we should lift up this Fixture to its own +// implementation file and only then could we reuse the Fixture in other AST +// unitttests. +struct CTAD : ASTImporterOptionSpecificTestBase {}; + +TEST_P(CTAD, DeductionGuideShouldReferToANonLocalTypedef) { + Decl *TU = getTuDecl( + R"( + typedef int U; + template struct A { +A(U, T); + }; + A a{(int)0, (int)0}; + )", + Lang_CXX17, "input.cc"); + auto *Guide = FirstDeclMatcher().match( + TU, cxxDeductionGuideDecl()); + auto *Typedef = FirstDeclMatcher().match( + TU, typedefNameDecl(hasName("U"))); + ParmVarDecl *Param = Guide->getParamDecl(0); + // The type of the first param (which is a typedef) should match the typedef + // in the global scope. + EXPECT_EQ(Param->getType()->getAs()->getDecl(), Typedef); +} + +TEST_P(CTAD, DeductionGuideShouldReferToANonLocalTypedefInParamPtr) { + Decl *TU = getTuDecl( + R"( + typedef int U; + template struct A { +A(U*, T); + }; + A a{(int*)0, (int)0}; + )", + Lang_CXX17, "input.cc"); + auto *Guide = FirstDeclMatcher().match( + TU, cxxDeductionGuideDecl()); + auto *Typedef = FirstDeclMatcher().match( + TU, typedefNameDecl(hasName("U"))); + ParmVarDecl *Param = Guide->getParamDecl(0); + EXPECT_EQ(Param->getType() +->getAs() +
[llvm-branch-commits] [clang] d14c631 - [analyzer][StdLibraryFunctionsChecker] Make close and mmap to accept -1 as fd
Author: Gabor Marton Date: 2020-12-08T16:58:30+01:00 New Revision: d14c63167315edfc4a4ad91fac9c866c6e0cb67f URL: https://github.com/llvm/llvm-project/commit/d14c63167315edfc4a4ad91fac9c866c6e0cb67f DIFF: https://github.com/llvm/llvm-project/commit/d14c63167315edfc4a4ad91fac9c866c6e0cb67f.diff LOG: [analyzer][StdLibraryFunctionsChecker] Make close and mmap to accept -1 as fd close: It is quite often that users chose to call close even if the fd is negative. Theoretically, it would be nicer to close only valid fds, but in practice the implementations of close just returns with EBADF in case of a non-valid fd param. So, we can eliminate many false positives if we let close to take -1 as an fd. Other negative values are very unlikely, because open and other fd factories return with -1 in case of failure. mmap: In the case of MAP_ANONYMOUS flag (which is supported e.g. in Linux) the mapping is not backed by any file; its contents are initialized to zero. The fd argument is ignored; however, some implementations require fd to be -1 if MAP_ANONYMOUS (or MAP_ANON) is specified, and portable applications should ensure this. Consequently, we must allow -1 as the 4th arg. Differential Revision: https://reviews.llvm.org/D92764 Added: Modified: clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp Removed: diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp index 8a34950ce7341..de825b2fee11f 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp @@ -1672,7 +1672,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( addToFunctionSummaryMap("close", Signature(ArgTypes{IntTy}, RetType{IntTy}), Summary(NoEvalCall) .ArgConstraint(ArgumentCondition( -0, WithinRange, Range(0, IntMax; +0, WithinRange, Range(-1, IntMax; // long fpathconf(int fildes, int name); addToFunctionSummaryMap("fpathconf", @@ -1734,7 +1734,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( Summary(NoEvalCall) .ArgConstraint(ArgumentCondition(1, WithinRange, Range(1, SizeMax))) .ArgConstraint( -ArgumentCondition(4, WithinRange, Range(0, IntMax; +ArgumentCondition(4, WithinRange, Range(-1, IntMax; Optional Off64_tTy = lookupTy("off64_t"); // void *mmap64(void *addr, size_t length, int prot, int flags, int fd, @@ -1746,7 +1746,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( Summary(NoEvalCall) .ArgConstraint(ArgumentCondition(1, WithinRange, Range(1, SizeMax))) .ArgConstraint( -ArgumentCondition(4, WithinRange, Range(0, IntMax; +ArgumentCondition(4, WithinRange, Range(-1, IntMax; // int pipe(int fildes[2]); addToFunctionSummaryMap( ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] febe750 - [analyzer][StdLibraryFunctionsChecker] Add more return value contraints
Author: Gabor Marton Date: 2020-12-08T17:04:29+01:00 New Revision: febe75032f6f8322cce1dcbba11a44559aaa14e3 URL: https://github.com/llvm/llvm-project/commit/febe75032f6f8322cce1dcbba11a44559aaa14e3 DIFF: https://github.com/llvm/llvm-project/commit/febe75032f6f8322cce1dcbba11a44559aaa14e3.diff LOG: [analyzer][StdLibraryFunctionsChecker] Add more return value contraints This time, we add contraints to functions that either return with [0, -1] or with a file descriptor. Differential Revision: https://reviews.llvm.org/D92771 Added: Modified: clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp Removed: diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp index de825b2fee11..f0710a658148 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp @@ -1322,21 +1322,31 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( .ArgConstraint(ArgumentCondition( 0, WithinRange, Range(0, LongMax; +const auto ReturnsZeroOrMinusOne = +ConstraintSet{ReturnValueCondition(WithinRange, Range(-1, 0))}; +const auto ReturnsFileDescriptor = +ConstraintSet{ReturnValueCondition(WithinRange, Range(-1, IntMax))}; + // int access(const char *pathname, int amode); addToFunctionSummaryMap( "access", Signature(ArgTypes{ConstCharPtrTy, IntTy}, RetType{IntTy}), -Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0; +Summary(NoEvalCall) +.Case(ReturnsZeroOrMinusOne) +.ArgConstraint(NotNull(ArgNo(0; // int faccessat(int dirfd, const char *pathname, int mode, int flags); addToFunctionSummaryMap( "faccessat", Signature(ArgTypes{IntTy, ConstCharPtrTy, IntTy, IntTy}, RetType{IntTy}), -Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(1; +Summary(NoEvalCall) +.Case(ReturnsZeroOrMinusOne) +.ArgConstraint(NotNull(ArgNo(1; // int dup(int fildes); addToFunctionSummaryMap("dup", Signature(ArgTypes{IntTy}, RetType{IntTy}), Summary(NoEvalCall) +.Case(ReturnsFileDescriptor) .ArgConstraint(ArgumentCondition( 0, WithinRange, Range(0, IntMax; @@ -1344,6 +1354,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( addToFunctionSummaryMap( "dup2", Signature(ArgTypes{IntTy, IntTy}, RetType{IntTy}), Summary(NoEvalCall) +.Case(ReturnsFileDescriptor) .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))) .ArgConstraint( ArgumentCondition(1, WithinRange, Range(0, IntMax; @@ -1352,6 +1363,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( addToFunctionSummaryMap("fdatasync", Signature(ArgTypes{IntTy}, RetType{IntTy}), Summary(NoEvalCall) +.Case(ReturnsZeroOrMinusOne) .ArgConstraint(ArgumentCondition( 0, WithinRange, Range(0, IntMax; @@ -1367,6 +1379,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( // int fsync(int fildes); addToFunctionSummaryMap("fsync", Signature(ArgTypes{IntTy}, RetType{IntTy}), Summary(NoEvalCall) +.Case(ReturnsZeroOrMinusOne) .ArgConstraint(ArgumentCondition( 0, WithinRange, Range(0, IntMax; @@ -1376,13 +1389,16 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( addToFunctionSummaryMap( "truncate", Signature(ArgTypes{ConstCharPtrTy, Off_tTy}, RetType{IntTy}), -Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0; +Summary(NoEvalCall) +.Case(ReturnsZeroOrMinusOne) +.ArgConstraint(NotNull(ArgNo(0; // int symlink(const char *oldpath, const char *newpath); addToFunctionSummaryMap( "symlink", Signature(ArgTypes{ConstCharPtrTy, ConstCharPtrTy}, RetType{IntTy}), Summary(NoEvalCall) +.Case(ReturnsZeroOrMinusOne) .ArgConstraint(NotNull(ArgNo(0))) .ArgConstraint(NotNull(ArgNo(1; @@ -1392,6 +1408,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( Signature(ArgTypes{ConstCharPtrTy, IntTy, ConstCharPtrTy}, RetType{IntTy}), Summary(NoEvalCall) +.Case(ReturnsZeroOrMinusOne) .ArgConstraint(NotNul
[llvm-branch-commits] [clang] a5e6590 - [ASTImporter] Support CXXDeductionGuideDecl with local typedef
Author: Gabor Marton Date: 2020-12-09T21:25:04+01:00 New Revision: a5e6590b15b17793d7a82f8b39998381acb73109 URL: https://github.com/llvm/llvm-project/commit/a5e6590b15b17793d7a82f8b39998381acb73109 DIFF: https://github.com/llvm/llvm-project/commit/a5e6590b15b17793d7a82f8b39998381acb73109.diff LOG: [ASTImporter] Support CXXDeductionGuideDecl with local typedef CXXDeductionGuideDecl with a local typedef has its own copy of the TypedefDecl with the CXXDeductionGuideDecl as the DeclContext of that TypedefDecl. ``` template struct A { typedef T U; A(U, T); }; A a{(int)0, (int)0}; ``` Related discussion on cfe-dev: http://lists.llvm.org/pipermail/cfe-dev/2020-November/067252.html Without this fix, when we import the CXXDeductionGuideDecl (via VisitFunctionDecl) then before creating the Decl we must import the FunctionType. However, the first parameter's type is the afore mentioned local typedef. So, we then start importing the TypedefDecl whose DeclContext is the CXXDeductionGuideDecl itself. The infinite loop is formed. ``` #0 clang::ASTNodeImporter::VisitCXXDeductionGuideDecl(clang::CXXDeductionGuideDecl*) clang/lib/AST/ASTImporter.cpp:3543:0 #1 clang::declvisitor::Base >::Visit(clang::Decl*) /home/egbomrt/WORK/llvm5/build/debug/tools/clang/include/clang/AST/DeclNodes.inc:405:0 #2 clang::ASTImporter::ImportImpl(clang::Decl*) clang/lib/AST/ASTImporter.cpp:8038:0 #3 clang::ASTImporter::Import(clang::Decl*) clang/lib/AST/ASTImporter.cpp:8200:0 #4 clang::ASTImporter::ImportContext(clang::DeclContext*) clang/lib/AST/ASTImporter.cpp:8297:0 #5 clang::ASTNodeImporter::ImportDeclContext(clang::Decl*, clang::DeclContext*&, clang::DeclContext*&) clang/lib/AST/ASTImporter.cpp:1852:0 #6 clang::ASTNodeImporter::ImportDeclParts(clang::NamedDecl*, clang::DeclContext*&, clang::DeclContext*&, clang::DeclarationName&, clang::NamedDecl*&, clang::SourceLocation&) clang/lib/AST/ASTImporter.cpp:1628:0 #7 clang::ASTNodeImporter::VisitTypedefNameDecl(clang::TypedefNameDecl*, bool) clang/lib/AST/ASTImporter.cpp:2419:0 #8 clang::ASTNodeImporter::VisitTypedefDecl(clang::TypedefDecl*) clang/lib/AST/ASTImporter.cpp:2500:0 #9 clang::declvisitor::Base >::Visit(clang::Decl*) /home/egbomrt/WORK/llvm5/build/debug/tools/clang/include/clang/AST/DeclNodes.inc:315:0 #10 clang::ASTImporter::ImportImpl(clang::Decl*) clang/lib/AST/ASTImporter.cpp:8038:0 #11 clang::ASTImporter::Import(clang::Decl*) clang/lib/AST/ASTImporter.cpp:8200:0 #12 llvm::Expected clang::ASTNodeImporter::import(clang::TypedefNameDecl*) clang/lib/AST/ASTImporter.cpp:165:0 #13 clang::ASTNodeImporter::VisitTypedefType(clang::TypedefType const*) clang/lib/AST/ASTImporter.cpp:1304:0 #14 clang::TypeVisitor >::Visit(clang::Type const*) /home/egbomrt/WORK/llvm5/build/debug/tools/clang/include/clang/AST/TypeNodes.inc:74:0 #15 clang::ASTImporter::Import(clang::QualType) clang/lib/AST/ASTImporter.cpp:8071:0 #16 llvm::Expected clang::ASTNodeImporter::import(clang::QualType const&) clang/lib/AST/ASTImporter.cpp:179:0 #17 clang::ASTNodeImporter::VisitFunctionProtoType(clang::FunctionProtoType const*) clang/lib/AST/ASTImporter.cpp:1244:0 #18 clang::TypeVisitor >::Visit(clang::Type const*) /home/egbomrt/WORK/llvm5/build/debug/tools/clang/include/clang/AST/TypeNodes.inc:47:0 #19 clang::ASTImporter::Import(clang::QualType) clang/lib/AST/ASTImporter.cpp:8071:0 #20 llvm::Expected clang::ASTNodeImporter::import(clang::QualType const&) clang/lib/AST/ASTImporter.cpp:179:0 #21 clang::QualType clang::ASTNodeImporter::importChecked(llvm::Error&, clang::QualType const&) clang/lib/AST/ASTImporter.cpp:198:0 #22 clang::ASTNodeImporter::VisitFunctionDecl(clang::FunctionDecl*) clang/lib/AST/ASTImporter.cpp:3313:0 #23 clang::ASTNodeImporter::VisitCXXDeductionGuideDecl(clang::CXXDeductionGuideDecl*) clang/lib/AST/ASTImporter.cpp:3543:0 ``` The fix is to first create the TypedefDecl and only then start to import the DeclContext. Basically, we could do this during the import of all other Decls (not just for typedefs). But it seems, there is only one another AST construct that has a similar cycle: a struct defined as a function parameter: ``` int struct_in_proto(struct data_t{int a;int b;} *d); ``` In that case, however, we had decided to return simply with an error back then because that seemed to be a very rare construct. Differential Revision: https://reviews.llvm.org/D92209 Added: Modified: clang/lib/AST/ASTImporter.cpp clang/unittests/AST/ASTImporterTest.cpp Removed: diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 50632efc281f..ea05f2ea4552 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -388,6 +388,8 @@ namespace clang { ExpectedType VisitObjCObjectPointerType(const ObjCObjectPointerType *T); // Importing declarations +Err