diff --git a/clang/include/clang/AST/ExprObjC.h b/clang/include/clang/AST/ExprObjC.h index 8ab7f49d4f03..60a57b471c05 100644 --- a/clang/include/clang/AST/ExprObjC.h +++ b/clang/include/clang/AST/ExprObjC.h @@ -300,8 +300,8 @@ public: return SourceRange(getBase()->getLocStart(), Loc); return SourceRange(ClassLoc, Loc); } - const Expr *getBase() const { return cast(Base); } - Expr *getBase() { return cast(Base); } + const Expr *getBase() const { return cast_or_null(Base); } + Expr *getBase() { return cast_or_null(Base); } void setBase(Expr *base) { Base = base; } SourceLocation getLocation() const { return Loc; } @@ -375,7 +375,7 @@ public: Expr **ArgExprs, unsigned NumArgs); explicit ObjCMessageExpr(EmptyShell Empty) - : Expr(ObjCMessageExprClass, Empty) {} + : Expr(ObjCMessageExprClass, Empty), SubExprs(0), NumArgs(0) {} ~ObjCMessageExpr() { delete [] SubExprs; @@ -418,7 +418,13 @@ public: /// getNumArgs - Return the number of actual arguments to this call. unsigned getNumArgs() const { return NumArgs; } - void setNumArgs(unsigned nArgs) { NumArgs = nArgs; } + void setNumArgs(unsigned nArgs) { + NumArgs = nArgs; + // FIXME: should always allocate SubExprs via the ASTContext's + // allocator. + if (!SubExprs) + SubExprs = new Stmt* [NumArgs + 1]; + } /// getArg - Return the specified argument. Expr *getArg(unsigned Arg) { diff --git a/clang/include/clang/Basic/IdentifierTable.h b/clang/include/clang/Basic/IdentifierTable.h index 083196a2c113..69b7bafbae75 100644 --- a/clang/include/clang/Basic/IdentifierTable.h +++ b/clang/include/clang/Basic/IdentifierTable.h @@ -412,6 +412,10 @@ public: void *getAsOpaquePtr() const { return reinterpret_cast(InfoPtr); } + + /// \brief Determine whether this is the empty selector. + bool isNull() const { return InfoPtr == 0; } + // Predicates to identify the selector type. bool isKeywordSelector() const { return getIdentifierInfoFlag() != ZeroArg; diff --git a/clang/include/clang/Frontend/PCHBitCodes.h b/clang/include/clang/Frontend/PCHBitCodes.h index 650da2857b57..a7d57560e6df 100644 --- a/clang/include/clang/Frontend/PCHBitCodes.h +++ b/clang/include/clang/Frontend/PCHBitCodes.h @@ -412,6 +412,8 @@ namespace clang { DECL_FIELD, /// \brief A VarDecl record. DECL_VAR, + /// \brief An ImplicitParamDecl record. + DECL_IMPLICIT_PARAM, /// \brief A ParmVarDecl record. DECL_PARM_VAR, /// \brief An OriginalParmVarDecl record. diff --git a/clang/lib/Basic/IdentifierTable.cpp b/clang/lib/Basic/IdentifierTable.cpp index 8b74b20032a9..69ee090b6e12 100644 --- a/clang/lib/Basic/IdentifierTable.cpp +++ b/clang/lib/Basic/IdentifierTable.cpp @@ -315,9 +315,9 @@ unsigned Selector::getNumArgs() const { } IdentifierInfo *Selector::getIdentifierInfoForSlot(unsigned argIndex) const { - if (IdentifierInfo *II = getAsIdentifierInfo()) { + if (getIdentifierInfoFlag()) { assert(argIndex == 0 && "illegal keyword index"); - return II; + return getAsIdentifierInfo(); } // We point to a MultiKeywordSelector (pointer doesn't contain any flags). MultiKeywordSelector *SI = reinterpret_cast(InfoPtr); @@ -346,6 +346,9 @@ std::string MultiKeywordSelector::getName() const { } std::string Selector::getAsString() const { + if (InfoPtr == 0) + return ""; + if (InfoPtr & ArgFlags) { IdentifierInfo *II = getAsIdentifierInfo(); diff --git a/clang/lib/Frontend/PCHReader.cpp b/clang/lib/Frontend/PCHReader.cpp index 375fcdddf545..ebfe77ccd787 100644 --- a/clang/lib/Frontend/PCHReader.cpp +++ b/clang/lib/Frontend/PCHReader.cpp @@ -82,6 +82,7 @@ namespace { void VisitFunctionDecl(FunctionDecl *FD); void VisitFieldDecl(FieldDecl *FD); void VisitVarDecl(VarDecl *VD); + void VisitImplicitParamDecl(ImplicitParamDecl *PD); void VisitParmVarDecl(ParmVarDecl *PD); void VisitOriginalParmVarDecl(OriginalParmVarDecl *PD); void VisitFileScopeAsmDecl(FileScopeAsmDecl *AD); @@ -200,7 +201,7 @@ void PCHDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) { if (Record[Idx++]) { // In practice, this won't be executed (since method definitions // don't occur in header files). - MD->setBody(cast(Reader.GetStmt(Record[Idx++]))); + MD->setBody(cast(Reader.ReadStmt())); MD->setSelfDecl(cast(Reader.GetDecl(Record[Idx++]))); MD->setCmdDecl(cast(Reader.GetDecl(Record[Idx++]))); } @@ -376,6 +377,10 @@ void PCHDeclReader::VisitVarDecl(VarDecl *VD) { VD->setInit(Reader.ReadExpr()); } +void PCHDeclReader::VisitImplicitParamDecl(ImplicitParamDecl *PD) { + VisitVarDecl(PD); +} + void PCHDeclReader::VisitParmVarDecl(ParmVarDecl *PD) { VisitVarDecl(PD); PD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]); @@ -504,8 +509,8 @@ namespace { unsigned VisitObjCSuperExpr(ObjCSuperExpr *E); unsigned VisitObjCForCollectionStmt(ObjCForCollectionStmt *); - unsigned VisitObjCCatchStmt(ObjCAtCatchStmt *); - unsigned VisitObjCFinallyStmt(ObjCAtFinallyStmt *); + unsigned VisitObjCAtCatchStmt(ObjCAtCatchStmt *); + unsigned VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *); unsigned VisitObjCAtTryStmt(ObjCAtTryStmt *); unsigned VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *); unsigned VisitObjCAtThrowStmt(ObjCAtThrowStmt *); @@ -1112,10 +1117,13 @@ unsigned PCHStmtReader::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { unsigned PCHStmtReader::VisitObjCKVCRefExpr(ObjCKVCRefExpr *E) { VisitExpr(E); - E->setGetterMethod(cast(Reader.GetDecl(Record[Idx++]))); - E->setSetterMethod(cast(Reader.GetDecl(Record[Idx++]))); - E->setClassProp(cast(Reader.GetDecl(Record[Idx++]))); - E->setBase(cast(StmtStack.back())); + E->setGetterMethod( + cast_or_null(Reader.GetDecl(Record[Idx++]))); + E->setSetterMethod( + cast_or_null(Reader.GetDecl(Record[Idx++]))); + E->setClassProp( + cast_or_null(Reader.GetDecl(Record[Idx++]))); + E->setBase(cast_or_null(StmtStack.back())); E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++])); E->setClassLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); return 1; @@ -1129,13 +1137,15 @@ unsigned PCHStmtReader::VisitObjCMessageExpr(ObjCMessageExpr *E) { E->setSelector(Reader.GetSelector(Record, Idx)); E->setMethodDecl(cast_or_null(Reader.GetDecl(Record[Idx++]))); - ObjCMessageExpr::ClassInfo CI; - CI.first = cast_or_null(Reader.GetDecl(Record[Idx++])); - CI.second = Reader.GetIdentifierInfo(Record, Idx); - if (E->getMethodDecl() == 0) + E->setReceiver( + cast_or_null(StmtStack[StmtStack.size() - E->getNumArgs() - 1])); + if (!E->getReceiver()) { + ObjCMessageExpr::ClassInfo CI; + CI.first = cast_or_null(Reader.GetDecl(Record[Idx++])); + CI.second = Reader.GetIdentifierInfo(Record, Idx); E->setClassInfo(CI); - - E->setReceiver(cast(StmtStack[StmtStack.size() - E->getNumArgs() - 1])); + } + for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) E->setArg(I, cast(StmtStack[StmtStack.size() - N + I])); return E->getNumArgs() + 1; @@ -1157,7 +1167,7 @@ unsigned PCHStmtReader::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) { return 3; } -unsigned PCHStmtReader::VisitObjCCatchStmt(ObjCAtCatchStmt *S) { +unsigned PCHStmtReader::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) { VisitStmt(S); S->setCatchBody(cast_or_null(StmtStack[StmtStack.size() - 2])); S->setNextCatchStmt(cast_or_null(StmtStack[StmtStack.size() - 1])); @@ -1167,7 +1177,7 @@ unsigned PCHStmtReader::VisitObjCCatchStmt(ObjCAtCatchStmt *S) { return 2; } -unsigned PCHStmtReader::VisitObjCFinallyStmt(ObjCAtFinallyStmt *S) { +unsigned PCHStmtReader::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) { VisitStmt(S); S->setFinallyBody(StmtStack.back()); S->setAtFinallyLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); @@ -2519,11 +2529,14 @@ Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) { break; } - case pch::DECL_VAR: { + case pch::DECL_VAR: D = VarDecl::Create(Context, 0, SourceLocation(), 0, QualType(), VarDecl::None, SourceLocation()); break; - } + + case pch::DECL_IMPLICIT_PARAM: + D = ImplicitParamDecl::Create(Context, 0, SourceLocation(), 0, QualType()); + break; case pch::DECL_PARM_VAR: { D = ParmVarDecl::Create(Context, 0, SourceLocation(), 0, QualType(), diff --git a/clang/lib/Frontend/PCHWriter.cpp b/clang/lib/Frontend/PCHWriter.cpp index 5037a091931a..41e3fb7fb591 100644 --- a/clang/lib/Frontend/PCHWriter.cpp +++ b/clang/lib/Frontend/PCHWriter.cpp @@ -260,6 +260,7 @@ namespace { void VisitFunctionDecl(FunctionDecl *D); void VisitFieldDecl(FieldDecl *D); void VisitVarDecl(VarDecl *D); + void VisitImplicitParamDecl(ImplicitParamDecl *D); void VisitParmVarDecl(ParmVarDecl *D); void VisitOriginalParmVarDecl(OriginalParmVarDecl *D); void VisitFileScopeAsmDecl(FileScopeAsmDecl *D); @@ -548,6 +549,11 @@ void PCHDeclWriter::VisitVarDecl(VarDecl *D) { Code = pch::DECL_VAR; } +void PCHDeclWriter::VisitImplicitParamDecl(ImplicitParamDecl *D) { + VisitVarDecl(D); + Code = pch::DECL_IMPLICIT_PARAM; +} + void PCHDeclWriter::VisitParmVarDecl(ParmVarDecl *D) { VisitVarDecl(D); Record.push_back(D->getObjCDeclQualifier()); // FIXME: stable encoding @@ -680,8 +686,8 @@ namespace { // Objective-C Statements void VisitObjCForCollectionStmt(ObjCForCollectionStmt *); - void VisitObjCCatchStmt(ObjCAtCatchStmt *); - void VisitObjCFinallyStmt(ObjCAtFinallyStmt *); + void VisitObjCAtCatchStmt(ObjCAtCatchStmt *); + void VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *); void VisitObjCAtTryStmt(ObjCAtTryStmt *); void VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *); void VisitObjCAtThrowStmt(ObjCAtThrowStmt *); @@ -1249,12 +1255,14 @@ void PCHStmtWriter::VisitObjCMessageExpr(ObjCMessageExpr *E) { Writer.AddSourceLocation(E->getRightLoc(), Record); Writer.AddSelectorRef(E->getSelector(), Record); Writer.AddDeclRef(E->getMethodDecl(), Record); // optional - - ObjCMessageExpr::ClassInfo CI = E->getClassInfo(); Writer.WriteSubStmt(E->getReceiver()); - Writer.AddDeclRef(CI.first, Record); - Writer.AddIdentifierRef(CI.second, Record); - + + if (!E->getReceiver()) { + ObjCMessageExpr::ClassInfo CI = E->getClassInfo(); + Writer.AddDeclRef(CI.first, Record); + Writer.AddIdentifierRef(CI.second, Record); + } + for (CallExpr::arg_iterator Arg = E->arg_begin(), ArgEnd = E->arg_end(); Arg != ArgEnd; ++Arg) Writer.WriteSubStmt(*Arg); @@ -1277,7 +1285,7 @@ void PCHStmtWriter::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) { Code = pch::STMT_OBJC_FOR_COLLECTION; } -void PCHStmtWriter::VisitObjCCatchStmt(ObjCAtCatchStmt *S) { +void PCHStmtWriter::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) { Writer.WriteSubStmt(S->getCatchBody()); Writer.WriteSubStmt(S->getNextCatchStmt()); Writer.AddDeclRef(S->getCatchParamDecl(), Record); @@ -1286,7 +1294,7 @@ void PCHStmtWriter::VisitObjCCatchStmt(ObjCAtCatchStmt *S) { Code = pch::STMT_OBJC_CATCH; } -void PCHStmtWriter::VisitObjCFinallyStmt(ObjCAtFinallyStmt *S) { +void PCHStmtWriter::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) { Writer.WriteSubStmt(S->getFinallyBody()); Writer.AddSourceLocation(S->getAtFinallyLoc(), Record); Code = pch::STMT_OBJC_FINALLY; diff --git a/clang/utils/pch-test.pl b/clang/utils/pch-test.pl index 4d7634ba0498..f9f4e9d83ccb 100755 --- a/clang/utils/pch-test.pl +++ b/clang/utils/pch-test.pl @@ -7,26 +7,30 @@ use POSIX; $exitcode = 0; - sub testfiles($$) { my $suffix = shift; my $language = shift; + my $passed = 0; + my $failed = 0; + my $skipped = 0; @files = `ls test/*/*.$suffix`; foreach $file (@files) { chomp($file); - print("."); my $code = system("clang-cc -fsyntax-only -x $language $file > /dev/null 2>&1"); if ($code == 0) { + print("."); $code = system("clang-cc -emit-pch -x $language -o $file.pch $file > /dev/null 2>&1"); if ($code == 0) { $code = system("clang-cc -include-pch $file.pch -x $language -ast-dump-full /dev/null > /dev/null 2>&1"); if ($code == 0) { + $passed++; } elsif (($code & 0xFF) == SIGINT) { exit($exitcode); } else { print("\n---Failed to dump AST file for \"$file\"---\n"); $exitcode = 1; + $failed++; } unlink "$file.pch"; } elsif (($code & 0xFF) == SIGINT) { @@ -34,11 +38,19 @@ sub testfiles($$) { } else { print("\n---Failed to build PCH file for \"$file\"---\n"); $exitcode = 1; + $failed++; } } elsif (($code & 0xFF) == SIGINT) { exit($exitcode); + } else { + print("x"); + $skipped++; } } + + print("\n\n$passed tests passed\n"); + print("$failed tests failed\n"); + print("$skipped tests skipped ('x')\n") } printf("-----Testing precompiled headers for C-----\n");