diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp | 856 |
1 files changed, 771 insertions, 85 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp index 9052278..86884b7 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp @@ -19,6 +19,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/CharUnits.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/EvaluatedExprVisitor.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/StmtObjC.h" @@ -27,8 +28,27 @@ #include "clang/Lex/Preprocessor.h" #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Triple.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstPrinter.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCObjectFileInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCTargetAsmParser.h" +#include "llvm/MC/MCParser/MCAsmLexer.h" +#include "llvm/MC/MCParser/MCAsmParser.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" using namespace clang; using namespace sema; @@ -150,10 +170,11 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { if (!E) return; + const Expr *WarnExpr; SourceLocation Loc; SourceRange R1, R2; if (SourceMgr.isInSystemMacro(E->getExprLoc()) || - !E->isUnusedResultAWarning(Loc, R1, R2, Context)) + !E->isUnusedResultAWarning(WarnExpr, Loc, R1, R2, Context)) return; // Okay, we have an unused result. Depending on what the base expression is, @@ -168,7 +189,7 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { if (DiagnoseUnusedComparison(*this, E)) return; - E = E->IgnoreParenImpCasts(); + E = WarnExpr; if (const CallExpr *CE = dyn_cast<CallExpr>(E)) { if (E->getType()->isVoidType()) return; @@ -226,6 +247,11 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { } } + if (E->isGLValue() && E->getType().isVolatileQualified()) { + Diag(Loc, diag::warn_unused_volatile) << R1 << R2; + return; + } + DiagRuntimeBehavior(Loc, 0, PDiag(DiagID) << R1 << R2); } @@ -361,12 +387,10 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl, } StmtResult Sema::ActOnAttributedStmt(SourceLocation AttrLoc, - const AttrVec &Attrs, + ArrayRef<const Attr*> Attrs, Stmt *SubStmt) { - // Fill in the declaration and return it. Variable length will require to - // change this to AttributedStmt::Create(Context, ....); - // and probably using ArrayRef - AttributedStmt *LS = new (Context) AttributedStmt(AttrLoc, Attrs, SubStmt); + // Fill in the declaration and return it. + AttributedStmt *LS = AttributedStmt::Create(Context, AttrLoc, Attrs, SubStmt); return Owned(LS); } @@ -519,16 +543,56 @@ Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, Expr *Cond, if (!Cond) return StmtError(); + class SwitchConvertDiagnoser : public ICEConvertDiagnoser { + Expr *Cond; + + public: + SwitchConvertDiagnoser(Expr *Cond) + : ICEConvertDiagnoser(false, true), Cond(Cond) { } + + virtual DiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc, + QualType T) { + return S.Diag(Loc, diag::err_typecheck_statement_requires_integer) << T; + } + + virtual DiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc, + QualType T) { + return S.Diag(Loc, diag::err_switch_incomplete_class_type) + << T << Cond->getSourceRange(); + } + + virtual DiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc, + QualType T, + QualType ConvTy) { + return S.Diag(Loc, diag::err_switch_explicit_conversion) << T << ConvTy; + } + + virtual DiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv, + QualType ConvTy) { + return S.Diag(Conv->getLocation(), diag::note_switch_conversion) + << ConvTy->isEnumeralType() << ConvTy; + } + + virtual DiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc, + QualType T) { + return S.Diag(Loc, diag::err_switch_multiple_conversions) << T; + } + + virtual DiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv, + QualType ConvTy) { + return S.Diag(Conv->getLocation(), diag::note_switch_conversion) + << ConvTy->isEnumeralType() << ConvTy; + } + + virtual DiagnosticBuilder diagnoseConversion(Sema &S, SourceLocation Loc, + QualType T, + QualType ConvTy) { + return DiagnosticBuilder::getEmpty(); + } + } SwitchDiagnoser(Cond); + CondResult - = ConvertToIntegralOrEnumerationType(SwitchLoc, Cond, - PDiag(diag::err_typecheck_statement_requires_integer), - PDiag(diag::err_switch_incomplete_class_type) - << Cond->getSourceRange(), - PDiag(diag::err_switch_explicit_conversion), - PDiag(diag::note_switch_conversion), - PDiag(diag::err_switch_multiple_conversions), - PDiag(diag::note_switch_conversion), - PDiag(0), + = ConvertToIntegralOrEnumerationType(SwitchLoc, Cond, SwitchDiagnoser, /*AllowScopedEnumerations*/ true); if (CondResult.isInvalid()) return StmtError(); Cond = CondResult.take(); @@ -609,7 +673,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, = CondExpr->isTypeDependent() || CondExpr->isValueDependent(); unsigned CondWidth = HasDependentValue ? 0 : Context.getIntWidth(CondTypeBeforePromotion); - bool CondIsSigned + bool CondIsSigned = CondTypeBeforePromotion->isSignedIntegerOrEnumerationType(); // Accumulate all of the case values in a vector so that we can sort them @@ -726,8 +790,30 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, if (i != 0 && CaseVals[i].first == CaseVals[i-1].first) { // If we have a duplicate, report it. - Diag(CaseVals[i].second->getLHS()->getLocStart(), - diag::err_duplicate_case) << CaseVals[i].first.toString(10); + // First, determine if either case value has a name + StringRef PrevString, CurrString; + Expr *PrevCase = CaseVals[i-1].second->getLHS()->IgnoreParenCasts(); + Expr *CurrCase = CaseVals[i].second->getLHS()->IgnoreParenCasts(); + if (DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(PrevCase)) { + PrevString = DeclRef->getDecl()->getName(); + } + if (DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(CurrCase)) { + CurrString = DeclRef->getDecl()->getName(); + } + llvm::SmallString<16> CaseValStr; + CaseVals[i-1].first.toString(CaseValStr); + + if (PrevString == CurrString) + Diag(CaseVals[i].second->getLHS()->getLocStart(), + diag::err_duplicate_case) << + (PrevString.empty() ? CaseValStr.str() : PrevString); + else + Diag(CaseVals[i].second->getLHS()->getLocStart(), + diag::err_duplicate_case_differing_expr) << + (PrevString.empty() ? CaseValStr.str() : PrevString) << + (CurrString.empty() ? CaseValStr.str() : CurrString) << + CaseValStr; + Diag(CaseVals[i-1].second->getLHS()->getLocStart(), diag::note_duplicate_case_prev); // FIXME: We really want to remove the bogus case stmt from the @@ -904,7 +990,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, << CondTypeBeforePromotion; } - llvm::APSInt Hi = + llvm::APSInt Hi = RI->second->getRHS()->EvaluateKnownConstInt(Context); AdjustAPSInt(Hi, CondWidth, CondIsSigned); while (EI != EIend && EI->first < Hi) @@ -952,12 +1038,12 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, switch (UnhandledNames.size()) { case 0: break; case 1: - Diag(CondExpr->getExprLoc(), TheDefaultStmt + Diag(CondExpr->getExprLoc(), TheDefaultStmt ? diag::warn_def_missing_case1 : diag::warn_missing_case1) << UnhandledNames[0]; break; case 2: - Diag(CondExpr->getExprLoc(), TheDefaultStmt + Diag(CondExpr->getExprLoc(), TheDefaultStmt ? diag::warn_def_missing_case2 : diag::warn_missing_case2) << UnhandledNames[0] << UnhandledNames[1]; break; @@ -990,6 +1076,55 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, return Owned(SS); } +void +Sema::DiagnoseAssignmentEnum(QualType DstType, QualType SrcType, + Expr *SrcExpr) { + unsigned DIAG = diag::warn_not_in_enum_assignement; + if (Diags.getDiagnosticLevel(DIAG, SrcExpr->getExprLoc()) + == DiagnosticsEngine::Ignored) + return; + + if (const EnumType *ET = DstType->getAs<EnumType>()) + if (!Context.hasSameType(SrcType, DstType) && + SrcType->isIntegerType()) { + if (!SrcExpr->isTypeDependent() && !SrcExpr->isValueDependent() && + SrcExpr->isIntegerConstantExpr(Context)) { + // Get the bitwidth of the enum value before promotions. + unsigned DstWith = Context.getIntWidth(DstType); + bool DstIsSigned = DstType->isSignedIntegerOrEnumerationType(); + + llvm::APSInt RhsVal = SrcExpr->EvaluateKnownConstInt(Context); + const EnumDecl *ED = ET->getDecl(); + typedef SmallVector<std::pair<llvm::APSInt, EnumConstantDecl*>, 64> + EnumValsTy; + EnumValsTy EnumVals; + + // Gather all enum values, set their type and sort them, + // allowing easier comparison with rhs constant. + for (EnumDecl::enumerator_iterator EDI = ED->enumerator_begin(); + EDI != ED->enumerator_end(); ++EDI) { + llvm::APSInt Val = EDI->getInitVal(); + AdjustAPSInt(Val, DstWith, DstIsSigned); + EnumVals.push_back(std::make_pair(Val, *EDI)); + } + if (EnumVals.empty()) + return; + std::stable_sort(EnumVals.begin(), EnumVals.end(), CmpEnumVals); + EnumValsTy::iterator EIend = + std::unique(EnumVals.begin(), EnumVals.end(), EqEnumVals); + + // See which case values aren't in enum. + EnumValsTy::const_iterator EI = EnumVals.begin(); + while (EI != EIend && EI->first < RhsVal) + EI++; + if (EI == EIend || EI->first != RhsVal) { + Diag(SrcExpr->getExprLoc(), diag::warn_not_in_enum_assignement) + << DstType; + } + } + } +} + StmtResult Sema::ActOnWhileStmt(SourceLocation WhileLoc, FullExprArg Cond, Decl *CondVar, Stmt *Body) { @@ -1037,6 +1172,215 @@ Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body, return Owned(new (Context) DoStmt(Body, Cond, DoLoc, WhileLoc, CondRParen)); } +namespace { + // This visitor will traverse a conditional statement and store all + // the evaluated decls into a vector. Simple is set to true if none + // of the excluded constructs are used. + class DeclExtractor : public EvaluatedExprVisitor<DeclExtractor> { + llvm::SmallPtrSet<VarDecl*, 8> &Decls; + llvm::SmallVector<SourceRange, 10> &Ranges; + bool Simple; +public: + typedef EvaluatedExprVisitor<DeclExtractor> Inherited; + + DeclExtractor(Sema &S, llvm::SmallPtrSet<VarDecl*, 8> &Decls, + llvm::SmallVector<SourceRange, 10> &Ranges) : + Inherited(S.Context), + Decls(Decls), + Ranges(Ranges), + Simple(true) {} + + bool isSimple() { return Simple; } + + // Replaces the method in EvaluatedExprVisitor. + void VisitMemberExpr(MemberExpr* E) { + Simple = false; + } + + // Any Stmt not whitelisted will cause the condition to be marked complex. + void VisitStmt(Stmt *S) { + Simple = false; + } + + void VisitBinaryOperator(BinaryOperator *E) { + Visit(E->getLHS()); + Visit(E->getRHS()); + } + + void VisitCastExpr(CastExpr *E) { + Visit(E->getSubExpr()); + } + + void VisitUnaryOperator(UnaryOperator *E) { + // Skip checking conditionals with derefernces. + if (E->getOpcode() == UO_Deref) + Simple = false; + else + Visit(E->getSubExpr()); + } + + void VisitConditionalOperator(ConditionalOperator *E) { + Visit(E->getCond()); + Visit(E->getTrueExpr()); + Visit(E->getFalseExpr()); + } + + void VisitParenExpr(ParenExpr *E) { + Visit(E->getSubExpr()); + } + + void VisitBinaryConditionalOperator(BinaryConditionalOperator *E) { + Visit(E->getOpaqueValue()->getSourceExpr()); + Visit(E->getFalseExpr()); + } + + void VisitIntegerLiteral(IntegerLiteral *E) { } + void VisitFloatingLiteral(FloatingLiteral *E) { } + void VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) { } + void VisitCharacterLiteral(CharacterLiteral *E) { } + void VisitGNUNullExpr(GNUNullExpr *E) { } + void VisitImaginaryLiteral(ImaginaryLiteral *E) { } + + void VisitDeclRefExpr(DeclRefExpr *E) { + VarDecl *VD = dyn_cast<VarDecl>(E->getDecl()); + if (!VD) return; + + Ranges.push_back(E->getSourceRange()); + + Decls.insert(VD); + } + + }; // end class DeclExtractor + + // DeclMatcher checks to see if the decls are used in a non-evauluated + // context. + class DeclMatcher : public EvaluatedExprVisitor<DeclMatcher> { + llvm::SmallPtrSet<VarDecl*, 8> &Decls; + bool FoundDecl; + +public: + typedef EvaluatedExprVisitor<DeclMatcher> Inherited; + + DeclMatcher(Sema &S, llvm::SmallPtrSet<VarDecl*, 8> &Decls, Stmt *Statement) : + Inherited(S.Context), Decls(Decls), FoundDecl(false) { + if (!Statement) return; + + Visit(Statement); + } + + void VisitReturnStmt(ReturnStmt *S) { + FoundDecl = true; + } + + void VisitBreakStmt(BreakStmt *S) { + FoundDecl = true; + } + + void VisitGotoStmt(GotoStmt *S) { + FoundDecl = true; + } + + void VisitCastExpr(CastExpr *E) { + if (E->getCastKind() == CK_LValueToRValue) + CheckLValueToRValueCast(E->getSubExpr()); + else + Visit(E->getSubExpr()); + } + + void CheckLValueToRValueCast(Expr *E) { + E = E->IgnoreParenImpCasts(); + + if (isa<DeclRefExpr>(E)) { + return; + } + + if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) { + Visit(CO->getCond()); + CheckLValueToRValueCast(CO->getTrueExpr()); + CheckLValueToRValueCast(CO->getFalseExpr()); + return; + } + + if (BinaryConditionalOperator *BCO = + dyn_cast<BinaryConditionalOperator>(E)) { + CheckLValueToRValueCast(BCO->getOpaqueValue()->getSourceExpr()); + CheckLValueToRValueCast(BCO->getFalseExpr()); + return; + } + + Visit(E); + } + + void VisitDeclRefExpr(DeclRefExpr *E) { + if (VarDecl *VD = dyn_cast<VarDecl>(E->getDecl())) + if (Decls.count(VD)) + FoundDecl = true; + } + + bool FoundDeclInUse() { return FoundDecl; } + + }; // end class DeclMatcher + + void CheckForLoopConditionalStatement(Sema &S, Expr *Second, + Expr *Third, Stmt *Body) { + // Condition is empty + if (!Second) return; + + if (S.Diags.getDiagnosticLevel(diag::warn_variables_not_in_loop_body, + Second->getLocStart()) + == DiagnosticsEngine::Ignored) + return; + + PartialDiagnostic PDiag = S.PDiag(diag::warn_variables_not_in_loop_body); + llvm::SmallPtrSet<VarDecl*, 8> Decls; + llvm::SmallVector<SourceRange, 10> Ranges; + DeclExtractor DE(S, Decls, Ranges); + DE.Visit(Second); + + // Don't analyze complex conditionals. + if (!DE.isSimple()) return; + + // No decls found. + if (Decls.size() == 0) return; + + // Don't warn on volatile, static, or global variables. + for (llvm::SmallPtrSet<VarDecl*, 8>::iterator I = Decls.begin(), + E = Decls.end(); + I != E; ++I) + if ((*I)->getType().isVolatileQualified() || + (*I)->hasGlobalStorage()) return; + + if (DeclMatcher(S, Decls, Second).FoundDeclInUse() || + DeclMatcher(S, Decls, Third).FoundDeclInUse() || + DeclMatcher(S, Decls, Body).FoundDeclInUse()) + return; + + // Load decl names into diagnostic. + if (Decls.size() > 4) + PDiag << 0; + else { + PDiag << Decls.size(); + for (llvm::SmallPtrSet<VarDecl*, 8>::iterator I = Decls.begin(), + E = Decls.end(); + I != E; ++I) + PDiag << (*I)->getDeclName(); + } + + // Load SourceRanges into diagnostic if there is room. + // Otherwise, load the SourceRange of the conditional expression. + if (Ranges.size() <= PartialDiagnostic::MaxArguments) + for (llvm::SmallVector<SourceRange, 10>::iterator I = Ranges.begin(), + E = Ranges.end(); + I != E; ++I) + PDiag << *I; + else + PDiag << Second->getSourceRange(); + + S.Diag(Ranges.begin()->getBegin(), PDiag); + } + +} // end namespace + StmtResult Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, Stmt *First, FullExprArg second, Decl *secondVar, @@ -1059,6 +1403,8 @@ Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, } } + CheckForLoopConditionalStatement(*this, second.get(), third.get(), Body); + ExprResult SecondResult(second.release()); VarDecl *ConditionVar = 0; if (secondVar) { @@ -1103,8 +1449,9 @@ StmtResult Sema::ActOnForEachLValueExpr(Expr *E) { } ExprResult -Sema::ActOnObjCForCollectionOperand(SourceLocation forLoc, Expr *collection) { - assert(collection); +Sema::CheckObjCForCollectionOperand(SourceLocation forLoc, Expr *collection) { + if (!collection) + return ExprError(); // Bail out early if we've got a type-dependent expression. if (collection->isTypeDependent()) return Owned(collection); @@ -1130,12 +1477,12 @@ Sema::ActOnObjCForCollectionOperand(SourceLocation forLoc, Expr *collection) { // If we have a forward-declared type, we can't do this check. // Under ARC, it is an error not to have a forward-declared class. - if (iface && + if (iface && RequireCompleteType(forLoc, QualType(objectType, 0), getLangOpts().ObjCAutoRefCount - ? PDiag(diag::err_arc_collection_forward) - << collection->getSourceRange() - : PDiag(0))) { + ? diag::err_arc_collection_forward + : 0, + collection)) { // Otherwise, if we have any useful type information, check that // the type declares the appropriate method. } else if (iface || !objectType->qual_empty()) { @@ -1151,7 +1498,7 @@ Sema::ActOnObjCForCollectionOperand(SourceLocation forLoc, Expr *collection) { // If there's an interface, look in both the public and private APIs. if (iface) { method = iface->lookupInstanceMethod(selector); - if (!method) method = LookupPrivateInstanceMethod(selector, iface); + if (!method) method = iface->lookupPrivateMethod(selector); } // Also check protocol qualifiers. @@ -1174,9 +1521,12 @@ Sema::ActOnObjCForCollectionOperand(SourceLocation forLoc, Expr *collection) { StmtResult Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc, - SourceLocation LParenLoc, - Stmt *First, Expr *Second, - SourceLocation RParenLoc, Stmt *Body) { + Stmt *First, Expr *collection, + SourceLocation RParenLoc) { + + ExprResult CollectionExprResult = + CheckObjCForCollectionOperand(ForLoc, collection); + if (First) { QualType FirstType; if (DeclStmt *DS = dyn_cast<DeclStmt>(First)) { @@ -1204,11 +1554,15 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc, if (!FirstType->isDependentType() && !FirstType->isObjCObjectPointerType() && !FirstType->isBlockPointerType()) - Diag(ForLoc, diag::err_selector_element_type) - << FirstType << First->getSourceRange(); + return StmtError(Diag(ForLoc, diag::err_selector_element_type) + << FirstType << First->getSourceRange()); } - return Owned(new (Context) ObjCForCollectionStmt(First, Second, Body, + if (CollectionExprResult.isInvalid()) + return StmtError(); + + return Owned(new (Context) ObjCForCollectionStmt(First, + CollectionExprResult.take(), 0, ForLoc, RParenLoc)); } @@ -1252,7 +1606,7 @@ static bool FinishForRangeVarDecl(Sema &SemaRef, VarDecl *Decl, Expr *Init, // In ARC, infer lifetime. // FIXME: ARC may want to turn this into 'const __unsafe_unretained' if // we're doing the equivalent of fast iteration. - if (SemaRef.getLangOpts().ObjCAutoRefCount && + if (SemaRef.getLangOpts().ObjCAutoRefCount && SemaRef.inferObjCARCLifetime(Decl)) Decl->setInvalidDecl(); @@ -1343,9 +1697,14 @@ static ExprResult BuildForRangeBeginEndCall(Sema &SemaRef, Scope *S, } -/// ActOnCXXForRangeStmt - Check and build a C++0x for-range statement. +static bool ObjCEnumerationCollection(Expr *Collection) { + return !Collection->isTypeDependent() + && Collection->getType()->getAs<ObjCObjectPointerType>() != 0; +} + +/// ActOnCXXForRangeStmt - Check and build a C++11 for-range statement. /// -/// C++0x [stmt.ranged]: +/// C++11 [stmt.ranged]: /// A range-based for statement is equivalent to /// /// { @@ -1362,12 +1721,15 @@ static ExprResult BuildForRangeBeginEndCall(Sema &SemaRef, Scope *S, /// The body of the loop is not available yet, since it cannot be analysed until /// we have determined the type of the for-range-declaration. StmtResult -Sema::ActOnCXXForRangeStmt(SourceLocation ForLoc, SourceLocation LParenLoc, +Sema::ActOnCXXForRangeStmt(SourceLocation ForLoc, Stmt *First, SourceLocation ColonLoc, Expr *Range, SourceLocation RParenLoc) { if (!First || !Range) return StmtError(); + if (ObjCEnumerationCollection(Range)) + return ActOnObjCForCollectionStmt(ForLoc, First, Range, RParenLoc); + DeclStmt *DS = dyn_cast<DeclStmt>(First); assert(DS && "first part of for range not a decl stmt"); @@ -1442,7 +1804,7 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc, QualType RangeType = Range->getType(); if (RequireCompleteType(RangeLoc, RangeType, - PDiag(diag::err_for_range_incomplete_type))) + diag::err_for_range_incomplete_type)) return StmtError(); // Build auto __begin = begin-expr, __end = end-expr. @@ -1618,6 +1980,17 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc, ColonLoc, RParenLoc)); } +/// FinishObjCForCollectionStmt - Attach the body to a objective-C foreach +/// statement. +StmtResult Sema::FinishObjCForCollectionStmt(Stmt *S, Stmt *B) { + if (!S || !B) + return StmtError(); + ObjCForCollectionStmt * ForStmt = cast<ObjCForCollectionStmt>(S); + + ForStmt->setBody(B); + return S; +} + /// FinishCXXForRangeStmt - Attach the body to a C++0x for-range statement. /// This is a separate step from ActOnCXXForRangeStmt because analysis of the /// body cannot be performed until after the type of the range variable is @@ -1626,6 +1999,9 @@ StmtResult Sema::FinishCXXForRangeStmt(Stmt *S, Stmt *B) { if (!S || !B) return StmtError(); + if (isa<ObjCForCollectionStmt>(S)) + return FinishObjCForCollectionStmt(S, B); + CXXForRangeStmt *ForStmt = cast<CXXForRangeStmt>(S); ForStmt->setBody(B); @@ -1723,7 +2099,7 @@ const VarDecl *Sema::getCopyElisionCandidate(QualType ReturnType, // ... the expression is the name of a non-volatile automatic object // (other than a function or catch-clause parameter)) ... const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E->IgnoreParens()); - if (!DR) + if (!DR || DR->refersToEnclosingLocal()) return 0; const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()); if (!VD) @@ -1776,8 +2152,7 @@ Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity, if (AllowNRVO && (NRVOCandidate || getCopyElisionCandidate(ResultType, Value, true))) { ImplicitCastExpr AsRvalue(ImplicitCastExpr::OnStack, - Value->getType(), CK_LValueToRValue, - Value, VK_XValue); + Value->getType(), CK_NoOp, Value, VK_XValue); Expr *InitExpr = &AsRvalue; InitializationKind Kind @@ -1812,8 +2187,7 @@ Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity, // Promote "AsRvalue" to the heap, since we now need this // expression node to persist. Value = ImplicitCastExpr::Create(Context, Value->getType(), - CK_LValueToRValue, Value, 0, - VK_XValue); + CK_NoOp, Value, 0, VK_XValue); // Complete type-checking the initialization of the return type // using the constructor we found. @@ -1840,8 +2214,12 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { // [expr.prim.lambda]p4 in C++11; block literals follow a superset of those // rules which allows multiple return statements. CapturingScopeInfo *CurCap = cast<CapturingScopeInfo>(getCurFunction()); + QualType FnRetType = CurCap->ReturnType; + + // For blocks/lambdas with implicit return types, we check each return + // statement individually, and deduce the common return type when the block + // or lambda is completed. if (CurCap->HasImplicitReturnType) { - QualType ReturnT; if (RetValExp && !isa<InitListExpr>(RetValExp)) { ExprResult Result = DefaultFunctionArrayLvalueConversion(RetValExp); if (Result.isInvalid()) @@ -1849,10 +2227,10 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { RetValExp = Result.take(); if (!RetValExp->isTypeDependent()) - ReturnT = RetValExp->getType(); + FnRetType = RetValExp->getType(); else - ReturnT = Context.DependentTy; - } else { + FnRetType = CurCap->ReturnType = Context.DependentTy; + } else { if (RetValExp) { // C++11 [expr.lambda.prim]p4 bans inferring the result from an // initializer list, because it is not an expression (even @@ -1861,21 +2239,14 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { << RetValExp->getSourceRange(); } - ReturnT = Context.VoidTy; - } - // We require the return types to strictly match here. - if (!CurCap->ReturnType.isNull() && - !CurCap->ReturnType->isDependentType() && - !ReturnT->isDependentType() && - !Context.hasSameType(ReturnT, CurCap->ReturnType)) { - Diag(ReturnLoc, diag::err_typecheck_missing_return_type_incompatible) - << ReturnT << CurCap->ReturnType - << (getCurLambda() != 0); - return StmtError(); + FnRetType = Context.VoidTy; } - CurCap->ReturnType = ReturnT; + + // Although we'll properly infer the type of the block once it's completed, + // make sure we provide a return type now for better error recovery. + if (CurCap->ReturnType.isNull()) + CurCap->ReturnType = FnRetType; } - QualType FnRetType = CurCap->ReturnType; assert(!FnRetType.isNull()); if (BlockScopeInfo *CurBlock = dyn_cast<BlockScopeInfo>(CurCap)) { @@ -1943,10 +2314,12 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { ReturnStmt *Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, NRVOCandidate); - // If we need to check for the named return value optimization, save the - // return statement in our scope for later processing. - if (getLangOpts().CPlusPlus && FnRetType->isRecordType() && - !CurContext->isDependentContext()) + // If we need to check for the named return value optimization, + // or if we need to infer the return type, + // save the return statement in our scope for later processing. + if (CurCap->HasImplicitReturnType || + (getLangOpts().CPlusPlus && FnRetType->isRecordType() && + !CurContext->isDependentContext())) FunctionScopes.back()->Returns.push_back(Result); return Owned(Result); @@ -1957,7 +2330,7 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { // Check for unexpanded parameter packs. if (RetValExp && DiagnoseUnexpandedParameterPack(RetValExp)) return StmtError(); - + if (isa<CapturingScopeInfo>(getCurFunction())) return ActOnCapScopeReturnStmt(ReturnLoc, RetValExp); @@ -1973,7 +2346,7 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { FnRetType = MD->getResultType(); if (MD->hasRelatedResultType() && MD->getClassInterface()) { // In the implementation of a method with a related return type, the - // type used to type-check the validity of return statements within the + // type used to type-check the validity of return statements within the // method body is a pointer to the type of the class being implemented. RelatedRetType = Context.getObjCInterfaceType(MD->getClassInterface()); RelatedRetType = Context.getObjCObjectPointerType(RelatedRetType); @@ -2064,7 +2437,7 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { // FIXME: The diagnostics here don't really describe what is happening. InitializedEntity Entity = InitializedEntity::InitializeTemporary(RelatedRetType); - + ExprResult Res = PerformCopyInitialization(Entity, SourceLocation(), RetValExp); if (Res.isInvalid()) { @@ -2108,7 +2481,7 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { if (getLangOpts().CPlusPlus && FnRetType->isRecordType() && !CurContext->isDependentContext()) FunctionScopes.back()->Returns.push_back(Result); - + return Owned(Result); } @@ -2147,18 +2520,17 @@ static bool CheckAsmLValue(const Expr *E, Sema &S) { /// isOperandMentioned - Return true if the specified operand # is mentioned /// anywhere in the decomposed asm string. -static bool isOperandMentioned(unsigned OpNo, +static bool isOperandMentioned(unsigned OpNo, ArrayRef<AsmStmt::AsmStringPiece> AsmStrPieces) { for (unsigned p = 0, e = AsmStrPieces.size(); p != e; ++p) { const AsmStmt::AsmStringPiece &Piece = AsmStrPieces[p]; if (!Piece.isOperand()) continue; - + // If this is a reference to the input and if the input was the smaller // one, then we have to reject this asm. if (Piece.getOperandNo() == OpNo) return true; } - return false; } @@ -2343,7 +2715,7 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple, // then we can promote the smaller one to a larger input and the asm string // won't notice. bool SmallerValueMentioned = false; - + // If this is a reference to the input and if the input was the smaller // one, then we have to reject this asm. if (isOperandMentioned(InputOpNo, Pieces)) { @@ -2364,7 +2736,7 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple, if (!SmallerValueMentioned && InputDomain != AD_Other && OutputConstraintInfos[TiedTo].allowsRegister()) continue; - + // Either both of the operands were mentioned or the smaller one was // mentioned. One more special case that we'll allow: if the tied input is // integer, unmentioned, and is a constant, then we'll allow truncating it @@ -2379,7 +2751,7 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple, NS->setInputExpr(i, InputExpr); continue; } - + Diag(InputExpr->getLocStart(), diag::err_asm_tying_incompatible_types) << InTy << OutTy << OutputExpr->getSourceRange() @@ -2390,6 +2762,323 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple, return Owned(NS); } +// isMSAsmKeyword - Return true if this is an MS-style inline asm keyword. These +// require special handling. +static bool isMSAsmKeyword(StringRef Name) { + bool Ret = llvm::StringSwitch<bool>(Name) + .Cases("EVEN", "ALIGN", true) // Alignment directives. + .Cases("LENGTH", "SIZE", "TYPE", true) // Type and variable sizes. + .Case("_emit", true) // _emit Pseudoinstruction. + .Default(false); + return Ret; +} + +static StringRef getSpelling(Sema &SemaRef, Token AsmTok) { + StringRef Asm; + SmallString<512> TokenBuf; + TokenBuf.resize(512); + bool StringInvalid = false; + Asm = SemaRef.PP.getSpelling(AsmTok, TokenBuf, &StringInvalid); + assert (!StringInvalid && "Expected valid string!"); + return Asm; +} + +static void patchMSAsmStrings(Sema &SemaRef, bool &IsSimple, + SourceLocation AsmLoc, + ArrayRef<Token> AsmToks, + const TargetInfo &TI, + std::vector<llvm::BitVector> &AsmRegs, + std::vector<llvm::BitVector> &AsmNames, + std::vector<std::string> &AsmStrings) { + assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!"); + + // Assume simple asm stmt until we parse a non-register identifer (or we just + // need to bail gracefully). + IsSimple = true; + + SmallString<512> Asm; + unsigned NumAsmStrings = 0; + for (unsigned i = 0, e = AsmToks.size(); i != e; ++i) { + + // Determine if this should be considered a new asm. + bool isNewAsm = i == 0 || AsmToks[i].isAtStartOfLine() || + AsmToks[i].is(tok::kw_asm); + + // Emit the previous asm string. + if (i && isNewAsm) { + AsmStrings[NumAsmStrings++] = Asm.c_str(); + if (AsmToks[i].is(tok::kw_asm)) { + ++i; // Skip __asm + assert (i != e && "Expected another token."); + } + } + + // Start a new asm string with the opcode. + if (isNewAsm) { + AsmRegs[NumAsmStrings].resize(AsmToks.size()); + AsmNames[NumAsmStrings].resize(AsmToks.size()); + + StringRef Piece = AsmToks[i].getIdentifierInfo()->getName(); + // MS-style inline asm keywords require special handling. + if (isMSAsmKeyword(Piece)) + IsSimple = false; + + // TODO: Verify this is a valid opcode. + Asm = Piece; + continue; + } + + if (i && AsmToks[i].hasLeadingSpace()) + Asm += ' '; + + // Check the operand(s). + switch (AsmToks[i].getKind()) { + default: + IsSimple = false; + Asm += getSpelling(SemaRef, AsmToks[i]); + break; + case tok::comma: Asm += ","; break; + case tok::colon: Asm += ":"; break; + case tok::l_square: Asm += "["; break; + case tok::r_square: Asm += "]"; break; + case tok::l_brace: Asm += "{"; break; + case tok::r_brace: Asm += "}"; break; + case tok::numeric_constant: + Asm += getSpelling(SemaRef, AsmToks[i]); + break; + case tok::identifier: { + IdentifierInfo *II = AsmToks[i].getIdentifierInfo(); + StringRef Name = II->getName(); + + // Valid register? + if (TI.isValidGCCRegisterName(Name)) { + AsmRegs[NumAsmStrings].set(i); + Asm += Name; + break; + } + + IsSimple = false; + + // MS-style inline asm keywords require special handling. + if (isMSAsmKeyword(Name)) { + IsSimple = false; + Asm += Name; + break; + } + + // FIXME: Why are we missing this segment register? + if (Name == "fs") { + Asm += Name; + break; + } + + // Lookup the identifier. + // TODO: Someone with more experience with clang should verify this the + // proper way of doing a symbol lookup. + DeclarationName DeclName(II); + Scope *CurScope = SemaRef.getCurScope(); + LookupResult R(SemaRef, DeclName, AsmLoc, Sema::LookupOrdinaryName); + if (!SemaRef.LookupName(R, CurScope, false/*AllowBuiltinCreation*/)) + break; + + assert (R.isSingleResult() && "Expected a single result?!"); + NamedDecl *Decl = R.getFoundDecl(); + switch (Decl->getKind()) { + default: + assert(0 && "Unknown decl kind."); + break; + case Decl::Var: { + case Decl::ParmVar: + AsmNames[NumAsmStrings].set(i); + + VarDecl *Var = cast<VarDecl>(Decl); + QualType Ty = Var->getType(); + (void)Ty; // Avoid warning. + // TODO: Patch identifier with valid operand. One potential idea is to + // probe the backend with type information to guess the possible + // operand. + break; + } + } + break; + } + } + } + + // Emit the final (and possibly only) asm string. + AsmStrings[NumAsmStrings] = Asm.c_str(); +} + +// Build the unmodified MSAsmString. +static std::string buildMSAsmString(Sema &SemaRef, + ArrayRef<Token> AsmToks, + unsigned &NumAsmStrings) { + assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!"); + NumAsmStrings = 0; + + SmallString<512> Asm; + for (unsigned i = 0, e = AsmToks.size(); i < e; ++i) { + bool isNewAsm = i == 0 || AsmToks[i].isAtStartOfLine() || + AsmToks[i].is(tok::kw_asm); + + if (isNewAsm) { + ++NumAsmStrings; + if (i) + Asm += '\n'; + if (AsmToks[i].is(tok::kw_asm)) { + i++; // Skip __asm + assert (i != e && "Expected another token"); + } + } + + if (i && AsmToks[i].hasLeadingSpace() && !isNewAsm) + Asm += ' '; + + Asm += getSpelling(SemaRef, AsmToks[i]); + } + return Asm.c_str(); +} + +StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, + SourceLocation LBraceLoc, + ArrayRef<Token> AsmToks, + SourceLocation EndLoc) { + // MS-style inline assembly is not fully supported, so emit a warning. + Diag(AsmLoc, diag::warn_unsupported_msasm); + SmallVector<StringRef,4> Clobbers; + std::set<std::string> ClobberRegs; + SmallVector<IdentifierInfo*, 4> Inputs; + SmallVector<IdentifierInfo*, 4> Outputs; + + // Empty asm statements don't need to instantiate the AsmParser, etc. + if (AsmToks.empty()) { + StringRef AsmString; + MSAsmStmt *NS = + new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, /*IsSimple*/ true, + /*IsVolatile*/ true, AsmToks, Inputs, Outputs, + AsmString, Clobbers, EndLoc); + return Owned(NS); + } + + unsigned NumAsmStrings; + std::string AsmString = buildMSAsmString(*this, AsmToks, NumAsmStrings); + + bool IsSimple; + std::vector<llvm::BitVector> Regs; + std::vector<llvm::BitVector> Names; + std::vector<std::string> PatchedAsmStrings; + + Regs.resize(NumAsmStrings); + Names.resize(NumAsmStrings); + PatchedAsmStrings.resize(NumAsmStrings); + + // Rewrite operands to appease the AsmParser. + patchMSAsmStrings(*this, IsSimple, AsmLoc, AsmToks, + Context.getTargetInfo(), Regs, Names, PatchedAsmStrings); + + // patchMSAsmStrings doesn't correctly patch non-simple asm statements. + if (!IsSimple) { + MSAsmStmt *NS = + new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, /*IsSimple*/ true, + /*IsVolatile*/ true, AsmToks, Inputs, Outputs, + AsmString, Clobbers, EndLoc); + return Owned(NS); + } + + // Initialize targets and assembly printers/parsers. + llvm::InitializeAllTargetInfos(); + llvm::InitializeAllTargetMCs(); + llvm::InitializeAllAsmParsers(); + + // Get the target specific parser. + std::string Error; + const std::string &TT = Context.getTargetInfo().getTriple().getTriple(); + const llvm::Target *TheTarget(llvm::TargetRegistry::lookupTarget(TT, Error)); + + OwningPtr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TT)); + OwningPtr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT)); + OwningPtr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo()); + OwningPtr<llvm::MCSubtargetInfo> + STI(TheTarget->createMCSubtargetInfo(TT, "", "")); + + for (unsigned i = 0, e = PatchedAsmStrings.size(); i != e; ++i) { + llvm::SourceMgr SrcMgr; + llvm::MCContext Ctx(*MAI, *MRI, MOFI.get(), &SrcMgr); + llvm::MemoryBuffer *Buffer = + llvm::MemoryBuffer::getMemBuffer(PatchedAsmStrings[i], "<inline asm>"); + + // Tell SrcMgr about this buffer, which is what the parser will pick up. + SrcMgr.AddNewSourceBuffer(Buffer, llvm::SMLoc()); + + OwningPtr<llvm::MCStreamer> Str(createNullStreamer(Ctx)); + OwningPtr<llvm::MCAsmParser> + Parser(createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI)); + OwningPtr<llvm::MCTargetAsmParser> + TargetParser(TheTarget->createMCAsmParser(*STI, *Parser)); + // Change to the Intel dialect. + Parser->setAssemblerDialect(1); + Parser->setTargetParser(*TargetParser.get()); + + // Prime the lexer. + Parser->Lex(); + + // Parse the opcode. + StringRef IDVal; + Parser->ParseIdentifier(IDVal); + + // Canonicalize the opcode to lower case. + SmallString<128> Opcode; + for (unsigned i = 0, e = IDVal.size(); i != e; ++i) + Opcode.push_back(tolower(IDVal[i])); + + // Parse the operands. + llvm::SMLoc IDLoc; + SmallVector<llvm::MCParsedAsmOperand*, 8> Operands; + bool HadError = TargetParser->ParseInstruction(Opcode.str(), IDLoc, + Operands); + assert (!HadError && "Unexpected error parsing instruction"); + + // Match the MCInstr. + SmallVector<llvm::MCInst, 2> Instrs; + HadError = TargetParser->MatchInstruction(IDLoc, Operands, Instrs); + assert (!HadError && "Unexpected error matching instruction"); + assert ((Instrs.size() == 1) && "Expected only a single instruction."); + + // Get the instruction descriptor. + llvm::MCInst Inst = Instrs[0]; + const llvm::MCInstrInfo *MII = TheTarget->createMCInstrInfo(); + const llvm::MCInstrDesc &Desc = MII->get(Inst.getOpcode()); + llvm::MCInstPrinter *IP = + TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI); + + // Build the list of clobbers. + for (unsigned i = 0, e = Desc.getNumDefs(); i != e; ++i) { + const llvm::MCOperand &Op = Inst.getOperand(i); + if (!Op.isReg()) + continue; + + std::string Reg; + llvm::raw_string_ostream OS(Reg); + IP->printRegName(OS, Op.getReg()); + + StringRef Clobber(OS.str()); + if (!Context.getTargetInfo().isValidClobber(Clobber)) + return StmtError(Diag(AsmLoc, diag::err_asm_unknown_register_name) << + Clobber); + ClobberRegs.insert(Reg); + } + } + for (std::set<std::string>::iterator I = ClobberRegs.begin(), + E = ClobberRegs.end(); I != E; ++I) + Clobbers.push_back(*I); + + MSAsmStmt *NS = + new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple, + /*IsVolatile*/ true, AsmToks, Inputs, Outputs, + AsmString, Clobbers, EndLoc); + return Owned(NS); +} + StmtResult Sema::ActOnObjCAtCatchStmt(SourceLocation AtLoc, SourceLocation RParen, Decl *Parm, @@ -2420,15 +3109,13 @@ Sema::ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try, Finally)); } -StmtResult Sema::BuildObjCAtThrowStmt(SourceLocation AtLoc, - Expr *Throw) { +StmtResult Sema::BuildObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw) { if (Throw) { - Throw = MaybeCreateExprWithCleanups(Throw); ExprResult Result = DefaultLvalueConversion(Throw); if (Result.isInvalid()) return StmtError(); - Throw = Result.take(); + Throw = MaybeCreateExprWithCleanups(Result.take()); QualType ThrowType = Throw->getType(); // Make sure the expression type is an ObjC pointer or "void *". if (!ThrowType->isDependentType() && @@ -2458,7 +3145,6 @@ Sema::ActOnObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw, if (!AtCatchParent) return StmtError(Diag(AtLoc, diag::error_rethrow_used_outside_catch)); } - return BuildObjCAtThrowStmt(AtLoc, Throw); } @@ -2646,17 +3332,17 @@ StmtResult Sema::BuildMSDependentExistsStmt(SourceLocation KeywordLoc, Stmt *Nested) { return new (Context) MSDependentExistsStmt(KeywordLoc, IsIfExists, - QualifierLoc, NameInfo, + QualifierLoc, NameInfo, cast<CompoundStmt>(Nested)); } -StmtResult Sema::ActOnMSDependentExistsStmt(SourceLocation KeywordLoc, +StmtResult Sema::ActOnMSDependentExistsStmt(SourceLocation KeywordLoc, bool IsIfExists, - CXXScopeSpec &SS, + CXXScopeSpec &SS, UnqualifiedId &Name, Stmt *Nested) { - return BuildMSDependentExistsStmt(KeywordLoc, IsIfExists, + return BuildMSDependentExistsStmt(KeywordLoc, IsIfExists, SS.getWithLocInContext(Context), GetNameFromUnqualifiedId(Name), Nested); |