diff options
Diffstat (limited to 'lib/Sema/SemaStmt.cpp')
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 930 |
1 files changed, 199 insertions, 731 deletions
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 86884b787339..f55174e05cc1 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -28,27 +28,10 @@ #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; @@ -177,6 +160,13 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { !E->isUnusedResultAWarning(WarnExpr, Loc, R1, R2, Context)) return; + // If this is a GNU statement expression expanded from a macro, it is probably + // unused because it is a function-like macro that can be used as either an + // expression or statement. Don't warn, because it is almost certainly a + // false positive. + if (isa<StmtExpr>(E) && Loc.isMacroID()) + return; + // Okay, we have an unused result. Depending on what the base expression is, // we might want to make a more specific diagnostic. Check for one of these // cases now. @@ -271,7 +261,7 @@ StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R, MultiStmtArg elts, bool isStmtExpr) { unsigned NumElts = elts.size(); - Stmt **Elts = reinterpret_cast<Stmt**>(elts.release()); + Stmt **Elts = elts.data(); // If we're in C89 mode, check that we don't have any decls after stmts. If // so, emit an extension diagnostic. if (!getLangOpts().C99 && !getLangOpts().CPlusPlus) { @@ -381,8 +371,10 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl, // Otherwise, things are good. Fill in the declaration and return it. LabelStmt *LS = new (Context) LabelStmt(IdentLoc, TheDecl, SubStmt); TheDecl->setStmt(LS); - if (!TheDecl->isGnuLocal()) + if (!TheDecl->isGnuLocal()) { + TheDecl->setLocStart(IdentLoc); TheDecl->setLocation(IdentLoc); + } return Owned(LS); } @@ -1566,25 +1558,6 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc, ForLoc, RParenLoc)); } -namespace { - -enum BeginEndFunction { - BEF_begin, - BEF_end -}; - -/// Build a variable declaration for a for-range statement. -static VarDecl *BuildForRangeVarDecl(Sema &SemaRef, SourceLocation Loc, - QualType Type, const char *Name) { - DeclContext *DC = SemaRef.CurContext; - IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name); - TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc); - VarDecl *Decl = VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, - TInfo, SC_Auto, SC_None); - Decl->setImplicit(); - return Decl; -} - /// Finish building a variable declaration for a for-range statement. /// \return true if an error occurs. static bool FinishForRangeVarDecl(Sema &SemaRef, VarDecl *Decl, Expr *Init, @@ -1617,12 +1590,14 @@ static bool FinishForRangeVarDecl(Sema &SemaRef, VarDecl *Decl, Expr *Init, return false; } +namespace { + /// Produce a note indicating which begin/end function was implicitly called -/// by a C++0x for-range statement. This is often not obvious from the code, +/// by a C++11 for-range statement. This is often not obvious from the code, /// nor from the diagnostics produced when analysing the implicit expressions /// required in a for-range statement. void NoteForRangeBeginEndFunction(Sema &SemaRef, Expr *E, - BeginEndFunction BEF) { + Sema::BeginEndFunction BEF) { CallExpr *CE = dyn_cast<CallExpr>(E); if (!CE) return; @@ -1643,56 +1618,16 @@ void NoteForRangeBeginEndFunction(Sema &SemaRef, Expr *E, << BEF << IsTemplate << Description << E->getType(); } -/// Build a call to 'begin' or 'end' for a C++0x for-range statement. If the -/// given LookupResult is non-empty, it is assumed to describe a member which -/// will be invoked. Otherwise, the function will be found via argument -/// dependent lookup. -static ExprResult BuildForRangeBeginEndCall(Sema &SemaRef, Scope *S, - SourceLocation Loc, - VarDecl *Decl, - BeginEndFunction BEF, - const DeclarationNameInfo &NameInfo, - LookupResult &MemberLookup, - Expr *Range) { - ExprResult CallExpr; - if (!MemberLookup.empty()) { - ExprResult MemberRef = - SemaRef.BuildMemberReferenceExpr(Range, Range->getType(), Loc, - /*IsPtr=*/false, CXXScopeSpec(), - /*TemplateKWLoc=*/SourceLocation(), - /*FirstQualifierInScope=*/0, - MemberLookup, - /*TemplateArgs=*/0); - if (MemberRef.isInvalid()) - return ExprError(); - CallExpr = SemaRef.ActOnCallExpr(S, MemberRef.get(), Loc, MultiExprArg(), - Loc, 0); - if (CallExpr.isInvalid()) - return ExprError(); - } else { - UnresolvedSet<0> FoundNames; - // C++0x [stmt.ranged]p1: For the purposes of this name lookup, namespace - // std is an associated namespace. - UnresolvedLookupExpr *Fn = - UnresolvedLookupExpr::Create(SemaRef.Context, /*NamingClass=*/0, - NestedNameSpecifierLoc(), NameInfo, - /*NeedsADL=*/true, /*Overloaded=*/false, - FoundNames.begin(), FoundNames.end(), - /*LookInStdNamespace=*/true); - CallExpr = SemaRef.BuildOverloadedCallExpr(S, Fn, Fn, Loc, &Range, 1, Loc, - 0, /*AllowTypoCorrection=*/false); - if (CallExpr.isInvalid()) { - SemaRef.Diag(Range->getLocStart(), diag::note_for_range_type) - << Range->getType(); - return ExprError(); - } - } - if (FinishForRangeVarDecl(SemaRef, Decl, CallExpr.get(), Loc, - diag::err_for_range_iter_deduction_failure)) { - NoteForRangeBeginEndFunction(SemaRef, CallExpr.get(), BEF); - return ExprError(); - } - return CallExpr; +/// Build a variable declaration for a for-range statement. +VarDecl *BuildForRangeVarDecl(Sema &SemaRef, SourceLocation Loc, + QualType Type, const char *Name) { + DeclContext *DC = SemaRef.CurContext; + IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name); + TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc); + VarDecl *Decl = VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, + TInfo, SC_Auto, SC_None); + Decl->setImplicit(); + return Decl; } } @@ -1723,7 +1658,7 @@ static bool ObjCEnumerationCollection(Expr *Collection) { StmtResult Sema::ActOnCXXForRangeStmt(SourceLocation ForLoc, Stmt *First, SourceLocation ColonLoc, Expr *Range, - SourceLocation RParenLoc) { + SourceLocation RParenLoc, BuildForRangeKind Kind) { if (!First || !Range) return StmtError(); @@ -1761,15 +1696,137 @@ Sema::ActOnCXXForRangeStmt(SourceLocation ForLoc, return BuildCXXForRangeStmt(ForLoc, ColonLoc, RangeDecl.get(), /*BeginEndDecl=*/0, /*Cond=*/0, /*Inc=*/0, DS, - RParenLoc); + RParenLoc, Kind); } -/// BuildCXXForRangeStmt - Build or instantiate a C++0x for-range statement. +/// \brief Create the initialization, compare, and increment steps for +/// the range-based for loop expression. +/// This function does not handle array-based for loops, +/// which are created in Sema::BuildCXXForRangeStmt. +/// +/// \returns a ForRangeStatus indicating success or what kind of error occurred. +/// BeginExpr and EndExpr are set and FRS_Success is returned on success; +/// CandidateSet and BEF are set and some non-success value is returned on +/// failure. +static Sema::ForRangeStatus BuildNonArrayForRange(Sema &SemaRef, Scope *S, + Expr *BeginRange, Expr *EndRange, + QualType RangeType, + VarDecl *BeginVar, + VarDecl *EndVar, + SourceLocation ColonLoc, + OverloadCandidateSet *CandidateSet, + ExprResult *BeginExpr, + ExprResult *EndExpr, + Sema::BeginEndFunction *BEF) { + DeclarationNameInfo BeginNameInfo( + &SemaRef.PP.getIdentifierTable().get("begin"), ColonLoc); + DeclarationNameInfo EndNameInfo(&SemaRef.PP.getIdentifierTable().get("end"), + ColonLoc); + + LookupResult BeginMemberLookup(SemaRef, BeginNameInfo, + Sema::LookupMemberName); + LookupResult EndMemberLookup(SemaRef, EndNameInfo, Sema::LookupMemberName); + + if (CXXRecordDecl *D = RangeType->getAsCXXRecordDecl()) { + // - if _RangeT is a class type, the unqualified-ids begin and end are + // looked up in the scope of class _RangeT as if by class member access + // lookup (3.4.5), and if either (or both) finds at least one + // declaration, begin-expr and end-expr are __range.begin() and + // __range.end(), respectively; + SemaRef.LookupQualifiedName(BeginMemberLookup, D); + SemaRef.LookupQualifiedName(EndMemberLookup, D); + + if (BeginMemberLookup.empty() != EndMemberLookup.empty()) { + SourceLocation RangeLoc = BeginVar->getLocation(); + *BEF = BeginMemberLookup.empty() ? Sema::BEF_end : Sema::BEF_begin; + + SemaRef.Diag(RangeLoc, diag::err_for_range_member_begin_end_mismatch) + << RangeLoc << BeginRange->getType() << *BEF; + return Sema::FRS_DiagnosticIssued; + } + } else { + // - otherwise, begin-expr and end-expr are begin(__range) and + // end(__range), respectively, where begin and end are looked up with + // argument-dependent lookup (3.4.2). For the purposes of this name + // lookup, namespace std is an associated namespace. + + } + + *BEF = Sema::BEF_begin; + Sema::ForRangeStatus RangeStatus = + SemaRef.BuildForRangeBeginEndCall(S, ColonLoc, ColonLoc, BeginVar, + Sema::BEF_begin, BeginNameInfo, + BeginMemberLookup, CandidateSet, + BeginRange, BeginExpr); + + if (RangeStatus != Sema::FRS_Success) + return RangeStatus; + if (FinishForRangeVarDecl(SemaRef, BeginVar, BeginExpr->get(), ColonLoc, + diag::err_for_range_iter_deduction_failure)) { + NoteForRangeBeginEndFunction(SemaRef, BeginExpr->get(), *BEF); + return Sema::FRS_DiagnosticIssued; + } + + *BEF = Sema::BEF_end; + RangeStatus = + SemaRef.BuildForRangeBeginEndCall(S, ColonLoc, ColonLoc, EndVar, + Sema::BEF_end, EndNameInfo, + EndMemberLookup, CandidateSet, + EndRange, EndExpr); + if (RangeStatus != Sema::FRS_Success) + return RangeStatus; + if (FinishForRangeVarDecl(SemaRef, EndVar, EndExpr->get(), ColonLoc, + diag::err_for_range_iter_deduction_failure)) { + NoteForRangeBeginEndFunction(SemaRef, EndExpr->get(), *BEF); + return Sema::FRS_DiagnosticIssued; + } + return Sema::FRS_Success; +} + +/// Speculatively attempt to dereference an invalid range expression. +/// If the attempt fails, this function will return a valid, null StmtResult +/// and emit no diagnostics. +static StmtResult RebuildForRangeWithDereference(Sema &SemaRef, Scope *S, + SourceLocation ForLoc, + Stmt *LoopVarDecl, + SourceLocation ColonLoc, + Expr *Range, + SourceLocation RangeLoc, + SourceLocation RParenLoc) { + // Determine whether we can rebuild the for-range statement with a + // dereferenced range expression. + ExprResult AdjustedRange; + { + Sema::SFINAETrap Trap(SemaRef); + + AdjustedRange = SemaRef.BuildUnaryOp(S, RangeLoc, UO_Deref, Range); + if (AdjustedRange.isInvalid()) + return StmtResult(); + + StmtResult SR = + SemaRef.ActOnCXXForRangeStmt(ForLoc, LoopVarDecl, ColonLoc, + AdjustedRange.get(), RParenLoc, + Sema::BFRK_Check); + if (SR.isInvalid()) + return StmtResult(); + } + + // The attempt to dereference worked well enough that it could produce a valid + // loop. Produce a fixit, and rebuild the loop with diagnostics enabled, in + // case there are any other (non-fatal) problems with it. + SemaRef.Diag(RangeLoc, diag::err_for_range_dereference) + << Range->getType() << FixItHint::CreateInsertion(RangeLoc, "*"); + return SemaRef.ActOnCXXForRangeStmt(ForLoc, LoopVarDecl, ColonLoc, + AdjustedRange.get(), RParenLoc, + Sema::BFRK_Rebuild); +} + +/// BuildCXXForRangeStmt - Build or instantiate a C++11 for-range statement. StmtResult Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc, Stmt *RangeDecl, Stmt *BeginEnd, Expr *Cond, Expr *Inc, Stmt *LoopVarDecl, - SourceLocation RParenLoc) { + SourceLocation RParenLoc, BuildForRangeKind Kind) { Scope *S = getCurScope(); DeclStmt *RangeDS = cast<DeclStmt>(RangeDecl); @@ -1855,50 +1912,43 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc, return StmtError(); } } else { - DeclarationNameInfo BeginNameInfo(&PP.getIdentifierTable().get("begin"), - ColonLoc); - DeclarationNameInfo EndNameInfo(&PP.getIdentifierTable().get("end"), - ColonLoc); - - LookupResult BeginMemberLookup(*this, BeginNameInfo, LookupMemberName); - LookupResult EndMemberLookup(*this, EndNameInfo, LookupMemberName); - - if (CXXRecordDecl *D = RangeType->getAsCXXRecordDecl()) { - // - if _RangeT is a class type, the unqualified-ids begin and end are - // looked up in the scope of class _RangeT as if by class member access - // lookup (3.4.5), and if either (or both) finds at least one - // declaration, begin-expr and end-expr are __range.begin() and - // __range.end(), respectively; - LookupQualifiedName(BeginMemberLookup, D); - LookupQualifiedName(EndMemberLookup, D); - - if (BeginMemberLookup.empty() != EndMemberLookup.empty()) { - Diag(ColonLoc, diag::err_for_range_member_begin_end_mismatch) - << RangeType << BeginMemberLookup.empty(); - return StmtError(); - } - } else { - // - otherwise, begin-expr and end-expr are begin(__range) and - // end(__range), respectively, where begin and end are looked up with - // argument-dependent lookup (3.4.2). For the purposes of this name - // lookup, namespace std is an associated namespace. + OverloadCandidateSet CandidateSet(RangeLoc); + Sema::BeginEndFunction BEFFailure; + ForRangeStatus RangeStatus = + BuildNonArrayForRange(*this, S, BeginRangeRef.get(), + EndRangeRef.get(), RangeType, + BeginVar, EndVar, ColonLoc, &CandidateSet, + &BeginExpr, &EndExpr, &BEFFailure); + + // If building the range failed, try dereferencing the range expression + // unless a diagnostic was issued or the end function is problematic. + if (Kind == BFRK_Build && RangeStatus == FRS_NoViableFunction && + BEFFailure == BEF_begin) { + StmtResult SR = RebuildForRangeWithDereference(*this, S, ForLoc, + LoopVarDecl, ColonLoc, + Range, RangeLoc, + RParenLoc); + if (SR.isInvalid() || SR.isUsable()) + return SR; } - BeginExpr = BuildForRangeBeginEndCall(*this, S, ColonLoc, BeginVar, - BEF_begin, BeginNameInfo, - BeginMemberLookup, - BeginRangeRef.get()); - if (BeginExpr.isInvalid()) - return StmtError(); - - EndExpr = BuildForRangeBeginEndCall(*this, S, ColonLoc, EndVar, - BEF_end, EndNameInfo, - EndMemberLookup, EndRangeRef.get()); - if (EndExpr.isInvalid()) + // Otherwise, emit diagnostics if we haven't already. + if (RangeStatus == FRS_NoViableFunction) { + Expr *Range = BEFFailure ? EndRangeRef.get() : BeginRangeRef.get(); + Diag(Range->getLocStart(), diag::err_for_range_invalid) + << RangeLoc << Range->getType() << BEFFailure; + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, + llvm::makeArrayRef(&Range, /*NumArgs=*/1)); + } + // Return an error if no fix was discovered. + if (RangeStatus != FRS_Success) return StmtError(); } - // C++0x [decl.spec.auto]p6: BeginType and EndType must be the same. + assert(!BeginExpr.isInvalid() && !EndExpr.isInvalid() && + "invalid range expression in for loop"); + + // C++11 [dcl.spec.auto]p7: BeginType and EndType must be the same. QualType BeginType = BeginVar->getType(), EndType = EndVar->getType(); if (!Context.hasSameType(BeginType, EndType)) { Diag(RangeLoc, diag::err_for_range_begin_end_types_differ) @@ -1930,6 +1980,8 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc, NotEqExpr = ActOnBooleanCondition(S, ColonLoc, NotEqExpr.get()); NotEqExpr = ActOnFinishFullExpr(NotEqExpr.get()); if (NotEqExpr.isInvalid()) { + Diag(RangeLoc, diag::note_for_range_invalid_iterator) + << RangeLoc << 0 << BeginRangeRef.get()->getType(); NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); if (!Context.hasSameType(BeginType, EndType)) NoteForRangeBeginEndFunction(*this, EndExpr.get(), BEF_end); @@ -1945,6 +1997,8 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc, IncrExpr = ActOnUnaryOp(S, ColonLoc, tok::plusplus, BeginRef.get()); IncrExpr = ActOnFinishFullExpr(IncrExpr.get()); if (IncrExpr.isInvalid()) { + Diag(RangeLoc, diag::note_for_range_invalid_iterator) + << RangeLoc << 2 << BeginRangeRef.get()->getType() ; NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); return StmtError(); } @@ -1957,12 +2011,15 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc, ExprResult DerefExpr = ActOnUnaryOp(S, ColonLoc, tok::star, BeginRef.get()); if (DerefExpr.isInvalid()) { + Diag(RangeLoc, diag::note_for_range_invalid_iterator) + << RangeLoc << 1 << BeginRangeRef.get()->getType(); NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); return StmtError(); } - // Attach *__begin as initializer for VD. - if (!LoopVar->isInvalidDecl()) { + // Attach *__begin as initializer for VD. Don't touch it if we're just + // trying to determine whether this would be a valid range. + if (!LoopVar->isInvalidDecl() && Kind != BFRK_Check) { AddInitializerToDecl(LoopVar, DerefExpr.get(), /*DirectInit=*/false, /*TypeMayContainAuto=*/true); if (LoopVar->isInvalidDecl()) @@ -1973,6 +2030,11 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc, RangeVar->setUsed(); } + // Don't bother to actually allocate the result if we're just trying to + // determine whether it would be valid. + if (Kind == BFRK_Check) + return StmtResult(); + return Owned(new (Context) CXXForRangeStmt(RangeDS, cast_or_null<DeclStmt>(BeginEndDecl.get()), NotEqExpr.take(), IncrExpr.take(), @@ -2485,600 +2547,6 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { return Owned(Result); } -/// CheckAsmLValue - GNU C has an extremely ugly extension whereby they silently -/// ignore "noop" casts in places where an lvalue is required by an inline asm. -/// We emulate this behavior when -fheinous-gnu-extensions is specified, but -/// provide a strong guidance to not use it. -/// -/// This method checks to see if the argument is an acceptable l-value and -/// returns false if it is a case we can handle. -static bool CheckAsmLValue(const Expr *E, Sema &S) { - // Type dependent expressions will be checked during instantiation. - if (E->isTypeDependent()) - return false; - - if (E->isLValue()) - return false; // Cool, this is an lvalue. - - // Okay, this is not an lvalue, but perhaps it is the result of a cast that we - // are supposed to allow. - const Expr *E2 = E->IgnoreParenNoopCasts(S.Context); - if (E != E2 && E2->isLValue()) { - if (!S.getLangOpts().HeinousExtensions) - S.Diag(E2->getLocStart(), diag::err_invalid_asm_cast_lvalue) - << E->getSourceRange(); - else - S.Diag(E2->getLocStart(), diag::warn_invalid_asm_cast_lvalue) - << E->getSourceRange(); - // Accept, even if we emitted an error diagnostic. - return false; - } - - // None of the above, just randomly invalid non-lvalue. - return true; -} - -/// isOperandMentioned - Return true if the specified operand # is mentioned -/// anywhere in the decomposed asm string. -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; -} - -StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple, - bool IsVolatile, unsigned NumOutputs, - unsigned NumInputs, IdentifierInfo **Names, - MultiExprArg constraints, MultiExprArg exprs, - Expr *asmString, MultiExprArg clobbers, - SourceLocation RParenLoc, bool MSAsm) { - unsigned NumClobbers = clobbers.size(); - StringLiteral **Constraints = - reinterpret_cast<StringLiteral**>(constraints.get()); - Expr **Exprs = exprs.get(); - StringLiteral *AsmString = cast<StringLiteral>(asmString); - StringLiteral **Clobbers = reinterpret_cast<StringLiteral**>(clobbers.get()); - - SmallVector<TargetInfo::ConstraintInfo, 4> OutputConstraintInfos; - - // The parser verifies that there is a string literal here. - if (!AsmString->isAscii()) - return StmtError(Diag(AsmString->getLocStart(),diag::err_asm_wide_character) - << AsmString->getSourceRange()); - - for (unsigned i = 0; i != NumOutputs; i++) { - StringLiteral *Literal = Constraints[i]; - if (!Literal->isAscii()) - return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) - << Literal->getSourceRange()); - - StringRef OutputName; - if (Names[i]) - OutputName = Names[i]->getName(); - - TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName); - if (!Context.getTargetInfo().validateOutputConstraint(Info)) - return StmtError(Diag(Literal->getLocStart(), - diag::err_asm_invalid_output_constraint) - << Info.getConstraintStr()); - - // Check that the output exprs are valid lvalues. - Expr *OutputExpr = Exprs[i]; - if (CheckAsmLValue(OutputExpr, *this)) { - return StmtError(Diag(OutputExpr->getLocStart(), - diag::err_asm_invalid_lvalue_in_output) - << OutputExpr->getSourceRange()); - } - - OutputConstraintInfos.push_back(Info); - } - - SmallVector<TargetInfo::ConstraintInfo, 4> InputConstraintInfos; - - for (unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) { - StringLiteral *Literal = Constraints[i]; - if (!Literal->isAscii()) - return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) - << Literal->getSourceRange()); - - StringRef InputName; - if (Names[i]) - InputName = Names[i]->getName(); - - TargetInfo::ConstraintInfo Info(Literal->getString(), InputName); - if (!Context.getTargetInfo().validateInputConstraint(OutputConstraintInfos.data(), - NumOutputs, Info)) { - return StmtError(Diag(Literal->getLocStart(), - diag::err_asm_invalid_input_constraint) - << Info.getConstraintStr()); - } - - Expr *InputExpr = Exprs[i]; - - // Only allow void types for memory constraints. - if (Info.allowsMemory() && !Info.allowsRegister()) { - if (CheckAsmLValue(InputExpr, *this)) - return StmtError(Diag(InputExpr->getLocStart(), - diag::err_asm_invalid_lvalue_in_input) - << Info.getConstraintStr() - << InputExpr->getSourceRange()); - } - - if (Info.allowsRegister()) { - if (InputExpr->getType()->isVoidType()) { - return StmtError(Diag(InputExpr->getLocStart(), - diag::err_asm_invalid_type_in_input) - << InputExpr->getType() << Info.getConstraintStr() - << InputExpr->getSourceRange()); - } - } - - ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]); - if (Result.isInvalid()) - return StmtError(); - - Exprs[i] = Result.take(); - InputConstraintInfos.push_back(Info); - } - - // Check that the clobbers are valid. - for (unsigned i = 0; i != NumClobbers; i++) { - StringLiteral *Literal = Clobbers[i]; - if (!Literal->isAscii()) - return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) - << Literal->getSourceRange()); - - StringRef Clobber = Literal->getString(); - - if (!Context.getTargetInfo().isValidClobber(Clobber)) - return StmtError(Diag(Literal->getLocStart(), - diag::err_asm_unknown_register_name) << Clobber); - } - - AsmStmt *NS = - new (Context) AsmStmt(Context, AsmLoc, IsSimple, IsVolatile, MSAsm, - NumOutputs, NumInputs, Names, Constraints, Exprs, - AsmString, NumClobbers, Clobbers, RParenLoc); - // Validate the asm string, ensuring it makes sense given the operands we - // have. - SmallVector<AsmStmt::AsmStringPiece, 8> Pieces; - unsigned DiagOffs; - if (unsigned DiagID = NS->AnalyzeAsmString(Pieces, Context, DiagOffs)) { - Diag(getLocationOfStringLiteralByte(AsmString, DiagOffs), DiagID) - << AsmString->getSourceRange(); - return StmtError(); - } - - // Validate tied input operands for type mismatches. - for (unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) { - TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i]; - - // If this is a tied constraint, verify that the output and input have - // either exactly the same type, or that they are int/ptr operands with the - // same size (int/long, int*/long, are ok etc). - if (!Info.hasTiedOperand()) continue; - - unsigned TiedTo = Info.getTiedOperand(); - unsigned InputOpNo = i+NumOutputs; - Expr *OutputExpr = Exprs[TiedTo]; - Expr *InputExpr = Exprs[InputOpNo]; - - if (OutputExpr->isTypeDependent() || InputExpr->isTypeDependent()) - continue; - - QualType InTy = InputExpr->getType(); - QualType OutTy = OutputExpr->getType(); - if (Context.hasSameType(InTy, OutTy)) - continue; // All types can be tied to themselves. - - // Decide if the input and output are in the same domain (integer/ptr or - // floating point. - enum AsmDomain { - AD_Int, AD_FP, AD_Other - } InputDomain, OutputDomain; - - if (InTy->isIntegerType() || InTy->isPointerType()) - InputDomain = AD_Int; - else if (InTy->isRealFloatingType()) - InputDomain = AD_FP; - else - InputDomain = AD_Other; - - if (OutTy->isIntegerType() || OutTy->isPointerType()) - OutputDomain = AD_Int; - else if (OutTy->isRealFloatingType()) - OutputDomain = AD_FP; - else - OutputDomain = AD_Other; - - // They are ok if they are the same size and in the same domain. This - // allows tying things like: - // void* to int* - // void* to int if they are the same size. - // double to long double if they are the same size. - // - uint64_t OutSize = Context.getTypeSize(OutTy); - uint64_t InSize = Context.getTypeSize(InTy); - if (OutSize == InSize && InputDomain == OutputDomain && - InputDomain != AD_Other) - continue; - - // If the smaller input/output operand is not mentioned in the asm string, - // 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)) { - // This is a use in the asm string of the smaller operand. Since we - // codegen this by promoting to a wider value, the asm will get printed - // "wrong". - SmallerValueMentioned |= InSize < OutSize; - } - if (isOperandMentioned(TiedTo, Pieces)) { - // If this is a reference to the output, and if the output is the larger - // value, then it's ok because we'll promote the input to the larger type. - SmallerValueMentioned |= OutSize < InSize; - } - - // If the smaller value wasn't mentioned in the asm string, and if the - // output was a register, just extend the shorter one to the size of the - // larger one. - 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 - // down to the size of the destination. - if (InputDomain == AD_Int && OutputDomain == AD_Int && - !isOperandMentioned(InputOpNo, Pieces) && - InputExpr->isEvaluatable(Context)) { - CastKind castKind = - (OutTy->isBooleanType() ? CK_IntegralToBoolean : CK_IntegralCast); - InputExpr = ImpCastExprToType(InputExpr, OutTy, castKind).take(); - Exprs[InputOpNo] = InputExpr; - NS->setInputExpr(i, InputExpr); - continue; - } - - Diag(InputExpr->getLocStart(), - diag::err_asm_tying_incompatible_types) - << InTy << OutTy << OutputExpr->getSourceRange() - << InputExpr->getSourceRange(); - return StmtError(); - } - - 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, @@ -3104,7 +2572,7 @@ Sema::ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try, getCurFunction()->setHasBranchProtectedScope(); unsigned NumCatchStmts = CatchStmts.size(); return Owned(ObjCAtTryStmt::Create(Context, AtLoc, Try, - CatchStmts.release(), + CatchStmts.data(), NumCatchStmts, Finally)); } @@ -3239,7 +2707,7 @@ Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, unsigned NumHandlers = RawHandlers.size(); assert(NumHandlers > 0 && "The parser shouldn't call this if there are no handlers."); - Stmt **Handlers = RawHandlers.get(); + Stmt **Handlers = RawHandlers.data(); SmallVector<TypeWithHandler, 8> TypesWithHandlers; |