/// \brief Build an Objective-C instance message expression. /// /// This routine takes care of both normal instance messages and /// instance messages to the superclass instance. /// /// \param Receiver The expression that computes the object that will /// receive this message. This may be empty, in which case we are /// sending to the superclass instance and \p SuperLoc must be a valid /// source location. /// /// \param ReceiverType The (static) type of the object receiving the /// message. When a \p Receiver expression is provided, this is the /// same type as that expression. For a superclass instance send, this /// is a pointer to the type of the superclass. /// /// \param SuperLoc The location of the "super" keyword in a /// superclass instance message. /// /// \param Sel The selector to which the message is being sent. /// /// \param Method The method that this instance message is invoking, if /// already known. /// /// \param LBracLoc The location of the opening square bracket ']'. /// /// \param RBrac The location of the closing square bracket ']'. /// /// \param Args The message arguments. Sema::OwningExprResult Sema::BuildInstanceMessage(ExprArg ReceiverE, QualType ReceiverType, SourceLocation SuperLoc, Selector Sel, ObjCMethodDecl *Method, SourceLocation LBracLoc, SourceLocation RBracLoc, MultiExprArg ArgsIn) { // If we have a receiver expression, perform appropriate promotions // and determine receiver type. Expr *Receiver = ReceiverE.takeAs<Expr>(); if (Receiver) { if (Receiver->isTypeDependent()) { // If the receiver is type-dependent, we can't type-check anything // at this point. Build a dependent expression. unsigned NumArgs = ArgsIn.size(); Expr **Args = reinterpret_cast<Expr **>(ArgsIn.release()); assert(SuperLoc.isInvalid() && "Message to super with dependent type"); return Owned(ObjCMessageExpr::Create(Context, Context.DependentTy, LBracLoc, Receiver, Sel, /*Method=*/0, Args, NumArgs, RBracLoc)); } // If necessary, apply function/array conversion to the receiver. // C99 6.7.5.3p[7,8]. DefaultFunctionArrayLvalueConversion(Receiver); ReceiverType = Receiver->getType(); } // The location of the receiver. SourceLocation Loc = SuperLoc.isValid()? SuperLoc : Receiver->getLocStart(); if (!Method) { // Handle messages to id. bool receiverIsId = ReceiverType->isObjCIdType(); if (receiverIsId || ReceiverType->isBlockPointerType() || (Receiver && Context.isObjCNSObjectType(Receiver->getType()))) { Method = LookupInstanceMethodInGlobalPool(Sel, SourceRange(LBracLoc, RBracLoc), receiverIsId); if (!Method) Method = LookupFactoryMethodInGlobalPool(Sel, SourceRange(LBracLoc, RBracLoc), receiverIsId); } else if (ReceiverType->isObjCClassType() || ReceiverType->isObjCQualifiedClassType()) { // Handle messages to Class. if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) { if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) { // First check the public methods in the class interface. Method = ClassDecl->lookupClassMethod(Sel); if (!Method) Method = LookupPrivateClassMethod(Sel, ClassDecl); // FIXME: if we still haven't found a method, we need to look in // protocols (if we have qualifiers). } if (Method && DiagnoseUseOfDecl(Method, Loc)) return ExprError(); } if (!Method) { // If not messaging 'self', look for any factory method named 'Sel'. if (!Receiver || !isSelfExpr(Receiver)) { Method = LookupFactoryMethodInGlobalPool(Sel, SourceRange(LBracLoc, RBracLoc), true); if (!Method) { // If no class (factory) method was found, check if an _instance_ // method of the same name exists in the root class only. Method = LookupInstanceMethodInGlobalPool(Sel, SourceRange(LBracLoc, RBracLoc), true); if (Method) if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext())) { if (ID->getSuperClass()) Diag(Loc, diag::warn_root_inst_method_not_found) << Sel << SourceRange(LBracLoc, RBracLoc); } } } } } else { ObjCInterfaceDecl* ClassDecl = 0; // We allow sending a message to a qualified ID ("id<foo>"), which is ok as // long as one of the protocols implements the selector (if not, warn). if (const ObjCObjectPointerType *QIdTy = ReceiverType->getAsObjCQualifiedIdType()) { // Search protocols for instance methods. for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(), E = QIdTy->qual_end(); I != E; ++I) { ObjCProtocolDecl *PDecl = *I; if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel))) break; // Since we aren't supporting "Class<foo>", look for a class method. if (PDecl && (Method = PDecl->lookupClassMethod(Sel))) break; } } else if (const ObjCObjectPointerType *OCIType = ReceiverType->getAsObjCInterfacePointerType()) { // We allow sending a message to a pointer to an interface (an object). ClassDecl = OCIType->getInterfaceDecl(); // FIXME: consider using LookupInstanceMethodInGlobalPool, since it will be // faster than the following method (which can do *many* linear searches). // The idea is to add class info to MethodPool. Method = ClassDecl->lookupInstanceMethod(Sel); if (!Method) { // Search protocol qualifiers. for (ObjCObjectPointerType::qual_iterator QI = OCIType->qual_begin(), E = OCIType->qual_end(); QI != E; ++QI) { if ((Method = (*QI)->lookupInstanceMethod(Sel))) break; } } if (!Method) { // If we have implementations in scope, check "private" methods. Method = LookupPrivateInstanceMethod(Sel, ClassDecl); if (!Method && (!Receiver || !isSelfExpr(Receiver))) { // If we still haven't found a method, look in the global pool. This // behavior isn't very desirable, however we need it for GCC // compatibility. FIXME: should we deviate?? if (OCIType->qual_empty()) { Method = LookupInstanceMethodInGlobalPool(Sel, SourceRange(LBracLoc, RBracLoc)); if (Method && !OCIType->getInterfaceDecl()->isForwardDecl()) Diag(Loc, diag::warn_maynot_respond) << OCIType->getInterfaceDecl()->getIdentifier() << Sel; } } } if (Method && DiagnoseUseOfDecl(Method, Loc)) return ExprError(); } else if (!Context.getObjCIdType().isNull() && (ReceiverType->isPointerType() || ReceiverType->isIntegerType())) { // Implicitly convert integers and pointers to 'id' but emit a warning. Diag(Loc, diag::warn_bad_receiver_type) << ReceiverType << Receiver->getSourceRange(); if (ReceiverType->isPointerType()) ImpCastExprToType(Receiver, Context.getObjCIdType(), CastExpr::CK_BitCast); else ImpCastExprToType(Receiver, Context.getObjCIdType(), CastExpr::CK_IntegralToPointer); ReceiverType = Receiver->getType(); } else if (getLangOptions().CPlusPlus && !PerformContextuallyConvertToObjCId(Receiver)) { if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Receiver)) { Receiver = ICE->getSubExpr(); ReceiverType = Receiver->getType(); } return BuildInstanceMessage(Owned(Receiver), ReceiverType, SuperLoc, Sel, Method, LBracLoc, RBracLoc, move(ArgsIn)); } else { // Reject other random receiver types (e.g. structs). Diag(Loc, diag::err_bad_receiver_type) << ReceiverType << Receiver->getSourceRange(); return ExprError(); } } } // Check the message arguments. unsigned NumArgs = ArgsIn.size(); Expr **Args = reinterpret_cast<Expr **>(ArgsIn.release()); QualType ReturnType; if (CheckMessageArgumentTypes(Args, NumArgs, Sel, Method, false, LBracLoc, RBracLoc, ReturnType)) return ExprError(); if (!ReturnType->isVoidType()) { if (RequireCompleteType(LBracLoc, ReturnType, diag::err_illegal_message_expr_incomplete_type)) return ExprError(); } // Construct the appropriate ObjCMessageExpr instance. Expr *Result; if (SuperLoc.isValid()) Result = ObjCMessageExpr::Create(Context, ReturnType, LBracLoc, SuperLoc, /*IsInstanceSuper=*/true, ReceiverType, Sel, Method, Args, NumArgs, RBracLoc); else Result = ObjCMessageExpr::Create(Context, ReturnType, LBracLoc, Receiver, Sel, Method, Args, NumArgs, RBracLoc); return MaybeBindToTemporary(Result); }
/// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function. /// "TheDeclarator" is the declarator that this will be added to. DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isAmbiguous, SourceLocation LParenLoc, ParamInfo *Params, unsigned NumParams, SourceLocation EllipsisLoc, SourceLocation RParenLoc, unsigned TypeQuals, bool RefQualifierIsLvalueRef, SourceLocation RefQualifierLoc, SourceLocation ConstQualifierLoc, SourceLocation VolatileQualifierLoc, SourceLocation RestrictQualifierLoc, SourceLocation MutableLoc, ExceptionSpecificationType ESpecType, SourceLocation ESpecLoc, ParsedType *Exceptions, SourceRange *ExceptionRanges, unsigned NumExceptions, Expr *NoexceptExpr, CachedTokens *ExceptionSpecTokens, SourceLocation LocalRangeBegin, SourceLocation LocalRangeEnd, Declarator &TheDeclarator, TypeResult TrailingReturnType) { assert(!(TypeQuals & DeclSpec::TQ_atomic) && "function cannot have _Atomic qualifier"); DeclaratorChunk I; I.Kind = Function; I.Loc = LocalRangeBegin; I.EndLoc = LocalRangeEnd; I.Fun.AttrList = nullptr; I.Fun.hasPrototype = hasProto; I.Fun.isVariadic = EllipsisLoc.isValid(); I.Fun.isAmbiguous = isAmbiguous; I.Fun.LParenLoc = LParenLoc.getRawEncoding(); I.Fun.EllipsisLoc = EllipsisLoc.getRawEncoding(); I.Fun.RParenLoc = RParenLoc.getRawEncoding(); I.Fun.DeleteParams = false; I.Fun.TypeQuals = TypeQuals; I.Fun.NumParams = NumParams; I.Fun.Params = nullptr; I.Fun.RefQualifierIsLValueRef = RefQualifierIsLvalueRef; I.Fun.RefQualifierLoc = RefQualifierLoc.getRawEncoding(); I.Fun.ConstQualifierLoc = ConstQualifierLoc.getRawEncoding(); I.Fun.VolatileQualifierLoc = VolatileQualifierLoc.getRawEncoding(); I.Fun.RestrictQualifierLoc = RestrictQualifierLoc.getRawEncoding(); I.Fun.MutableLoc = MutableLoc.getRawEncoding(); I.Fun.ExceptionSpecType = ESpecType; I.Fun.ExceptionSpecLoc = ESpecLoc.getRawEncoding(); I.Fun.NumExceptions = 0; I.Fun.Exceptions = nullptr; I.Fun.NoexceptExpr = nullptr; I.Fun.HasTrailingReturnType = TrailingReturnType.isUsable() || TrailingReturnType.isInvalid(); I.Fun.TrailingReturnType = TrailingReturnType.get(); assert(I.Fun.TypeQuals == TypeQuals && "bitfield overflow"); assert(I.Fun.ExceptionSpecType == ESpecType && "bitfield overflow"); // new[] a parameter array if needed. if (NumParams) { // If the 'InlineParams' in Declarator is unused and big enough, put our // parameter list there (in an effort to avoid new/delete traffic). If it // is already used (consider a function returning a function pointer) or too // small (function with too many parameters), go to the heap. if (!TheDeclarator.InlineParamsUsed && NumParams <= llvm::array_lengthof(TheDeclarator.InlineParams)) { I.Fun.Params = TheDeclarator.InlineParams; I.Fun.DeleteParams = false; TheDeclarator.InlineParamsUsed = true; } else { I.Fun.Params = new DeclaratorChunk::ParamInfo[NumParams]; I.Fun.DeleteParams = true; } memcpy(I.Fun.Params, Params, sizeof(Params[0]) * NumParams); } // Check what exception specification information we should actually store. switch (ESpecType) { default: break; // By default, save nothing. case EST_Dynamic: // new[] an exception array if needed if (NumExceptions) { I.Fun.NumExceptions = NumExceptions; I.Fun.Exceptions = new DeclaratorChunk::TypeAndRange[NumExceptions]; for (unsigned i = 0; i != NumExceptions; ++i) { I.Fun.Exceptions[i].Ty = Exceptions[i]; I.Fun.Exceptions[i].Range = ExceptionRanges[i]; } } break; case EST_ComputedNoexcept: I.Fun.NoexceptExpr = NoexceptExpr; break; case EST_Unparsed: I.Fun.ExceptionSpecTokens = ExceptionSpecTokens; break; } return I; }
/// ExpandBuiltinMacro - If an identifier token is read that is to be expanded /// as a builtin macro, handle it and return the next token as 'Tok'. void Preprocessor::ExpandBuiltinMacro(Token &Tok) { // Figure out which token this is. IdentifierInfo *II = Tok.getIdentifierInfo(); assert(II && "Can't be a macro without id info!"); // If this is an _Pragma or Microsoft __pragma directive, expand it, // invoke the pragma handler, then lex the token after it. if (II == Ident_Pragma) return Handle_Pragma(Tok); else if (II == Ident__pragma) // in non-MS mode this is null return HandleMicrosoft__pragma(Tok); ++NumBuiltinMacroExpanded; llvm::SmallString<128> TmpBuffer; llvm::raw_svector_ostream OS(TmpBuffer); // Set up the return result. Tok.setIdentifierInfo(0); Tok.clearFlag(Token::NeedsCleaning); if (II == Ident__LINE__) { // C99 6.10.8: "__LINE__: The presumed line number (within the current // source file) of the current source line (an integer constant)". This can // be affected by #line. SourceLocation Loc = Tok.getLocation(); // Advance to the location of the first _, this might not be the first byte // of the token if it starts with an escaped newline. Loc = AdvanceToTokenCharacter(Loc, 0); // One wrinkle here is that GCC expands __LINE__ to location of the *end* of // a macro instantiation. This doesn't matter for object-like macros, but // can matter for a function-like macro that expands to contain __LINE__. // Skip down through instantiation points until we find a file loc for the // end of the instantiation history. Loc = SourceMgr.getInstantiationRange(Loc).second; PresumedLoc PLoc = SourceMgr.getPresumedLoc(Loc); // __LINE__ expands to a simple numeric value. OS << PLoc.getLine(); Tok.setKind(tok::numeric_constant); } else if (II == Ident__FILE__ || II == Ident__BASE_FILE__) { // C99 6.10.8: "__FILE__: The presumed name of the current source file (a // character string literal)". This can be affected by #line. PresumedLoc PLoc = SourceMgr.getPresumedLoc(Tok.getLocation()); // __BASE_FILE__ is a GNU extension that returns the top of the presumed // #include stack instead of the current file. if (II == Ident__BASE_FILE__) { SourceLocation NextLoc = PLoc.getIncludeLoc(); while (NextLoc.isValid()) { PLoc = SourceMgr.getPresumedLoc(NextLoc); NextLoc = PLoc.getIncludeLoc(); } } // Escape this filename. Turn '\' -> '\\' '"' -> '\"' llvm::SmallString<128> FN; FN += PLoc.getFilename(); Lexer::Stringify(FN); OS << '"' << FN.str() << '"'; Tok.setKind(tok::string_literal); } else if (II == Ident__DATE__) { if (!DATELoc.isValid()) ComputeDATE_TIME(DATELoc, TIMELoc, *this); Tok.setKind(tok::string_literal); Tok.setLength(strlen("\"Mmm dd yyyy\"")); Tok.setLocation(SourceMgr.createInstantiationLoc(DATELoc, Tok.getLocation(), Tok.getLocation(), Tok.getLength())); return; } else if (II == Ident__TIME__) { if (!TIMELoc.isValid()) ComputeDATE_TIME(DATELoc, TIMELoc, *this); Tok.setKind(tok::string_literal); Tok.setLength(strlen("\"hh:mm:ss\"")); Tok.setLocation(SourceMgr.createInstantiationLoc(TIMELoc, Tok.getLocation(), Tok.getLocation(), Tok.getLength())); return; } else if (II == Ident__INCLUDE_LEVEL__) { // Compute the presumed include depth of this token. This can be affected // by GNU line markers. unsigned Depth = 0; PresumedLoc PLoc = SourceMgr.getPresumedLoc(Tok.getLocation()); PLoc = SourceMgr.getPresumedLoc(PLoc.getIncludeLoc()); for (; PLoc.isValid(); ++Depth) PLoc = SourceMgr.getPresumedLoc(PLoc.getIncludeLoc()); // __INCLUDE_LEVEL__ expands to a simple numeric value. OS << Depth; Tok.setKind(tok::numeric_constant); } else if (II == Ident__TIMESTAMP__) { // MSVC, ICC, GCC, VisualAge C++ extension. The generated string should be // of the form "Ddd Mmm dd hh::mm::ss yyyy", which is returned by asctime. // Get the file that we are lexing out of. If we're currently lexing from // a macro, dig into the include stack. const FileEntry *CurFile = 0; PreprocessorLexer *TheLexer = getCurrentFileLexer(); if (TheLexer) CurFile = SourceMgr.getFileEntryForID(TheLexer->getFileID()); const char *Result; if (CurFile) { time_t TT = CurFile->getModificationTime(); struct tm *TM = localtime(&TT); Result = asctime(TM); } else { Result = "??? ??? ?? ??:??:?? ????\n"; } // Surround the string with " and strip the trailing newline. OS << '"' << llvm::StringRef(Result, strlen(Result)-1) << '"'; Tok.setKind(tok::string_literal); } else if (II == Ident__COUNTER__) { // __COUNTER__ expands to a simple numeric value. OS << CounterValue++; Tok.setKind(tok::numeric_constant); } else if (II == Ident__has_feature || II == Ident__has_builtin) { // The argument to these two builtins should be a parenthesized identifier. SourceLocation StartLoc = Tok.getLocation(); bool IsValid = false; IdentifierInfo *FeatureII = 0; // Read the '('. Lex(Tok); if (Tok.is(tok::l_paren)) { // Read the identifier Lex(Tok); if (Tok.is(tok::identifier)) { FeatureII = Tok.getIdentifierInfo(); // Read the ')'. Lex(Tok); if (Tok.is(tok::r_paren)) IsValid = true; } } bool Value = false; if (!IsValid) Diag(StartLoc, diag::err_feature_check_malformed); else if (II == Ident__has_builtin) { // Check for a builtin is trivial. Value = FeatureII->getBuiltinID() != 0; } else { assert(II == Ident__has_feature && "Must be feature check"); Value = HasFeature(*this, FeatureII); } OS << (int)Value; Tok.setKind(tok::numeric_constant); } else if (II == Ident__has_include || II == Ident__has_include_next) { // The argument to these two builtins should be a parenthesized // file name string literal using angle brackets (<>) or // double-quotes (""). bool Value = false; bool IsValid; if (II == Ident__has_include) IsValid = EvaluateHasInclude(Value, Tok, II, *this); else IsValid = EvaluateHasIncludeNext(Value, Tok, II, *this); OS << (int)Value; Tok.setKind(tok::numeric_constant); } else { assert(0 && "Unknown identifier!"); } CreateString(OS.str().data(), OS.str().size(), Tok, Tok.getLocation()); }
// #pragma unused(identifier) void PragmaUnusedHandler::HandlePragma(Preprocessor &PP, Token &UnusedTok) { // FIXME: Should we be expanding macros here? My guess is no. SourceLocation UnusedLoc = UnusedTok.getLocation(); // Lex the left '('. Token Tok; PP.Lex(Tok); if (Tok.isNot(tok::l_paren)) { PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused"; return; } SourceLocation LParenLoc = Tok.getLocation(); // Lex the declaration reference(s). llvm::SmallVector<Token, 5> Identifiers; SourceLocation RParenLoc; bool LexID = true; while (true) { PP.Lex(Tok); if (LexID) { if (Tok.is(tok::identifier)) { Identifiers.push_back(Tok); LexID = false; continue; } // Illegal token! PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var); return; } // We are execting a ')' or a ','. if (Tok.is(tok::comma)) { LexID = true; continue; } if (Tok.is(tok::r_paren)) { RParenLoc = Tok.getLocation(); break; } // Illegal token! PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc); return; } PP.Lex(Tok); if (Tok.isNot(tok::eom)) { PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "unused"; return; } // Verify that we have a location for the right parenthesis. assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'"); assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments"); // Perform the action to handle the pragma. Actions.ActOnPragmaUnused(Identifiers.data(), Identifiers.size(), parser.CurScope, UnusedLoc, LParenLoc, RParenLoc); }
void out(const SourceLocation &loc) { if (!loc.isValid()) return; out(toString(loc), loc); }
bool SanitizerBlacklist::isBlacklistedLocation(SourceLocation Loc, StringRef Category) const { return Loc.isValid() && isBlacklistedFile(SM.getFilename(SM.getFileLoc(Loc)), Category); }
/// \brief Parse a header declaration. /// /// header-declaration: /// 'umbrella'[opt] 'header' string-literal void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc) { assert(Tok.is(MMToken::HeaderKeyword)); consumeToken(); bool Umbrella = UmbrellaLoc.isValid(); // Parse the header name. if (!Tok.is(MMToken::StringLiteral)) { Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) << "header"; HadError = true; return; } std::string FileName = Tok.getString(); SourceLocation FileNameLoc = consumeToken(); // Check whether we already have an umbrella. if (Umbrella && ActiveModule->Umbrella) { Diags.Report(FileNameLoc, diag::err_mmap_umbrella_clash) << ActiveModule->getFullModuleName(); HadError = true; return; } // Look for this file. const FileEntry *File = 0; const FileEntry *BuiltinFile = 0; SmallString<128> PathName; if (llvm::sys::path::is_absolute(FileName)) { PathName = FileName; File = SourceMgr.getFileManager().getFile(PathName); } else if (const DirectoryEntry *Dir = getOverriddenHeaderSearchDir()) { PathName = Dir->getName(); llvm::sys::path::append(PathName, FileName); File = SourceMgr.getFileManager().getFile(PathName); } else { // Search for the header file within the search directory. PathName = Directory->getName(); unsigned PathLength = PathName.size(); if (ActiveModule->isPartOfFramework()) { appendSubframeworkPaths(ActiveModule, PathName); // Check whether this file is in the public headers. llvm::sys::path::append(PathName, "Headers"); llvm::sys::path::append(PathName, FileName); File = SourceMgr.getFileManager().getFile(PathName); if (!File) { // Check whether this file is in the private headers. PathName.resize(PathLength); llvm::sys::path::append(PathName, "PrivateHeaders"); llvm::sys::path::append(PathName, FileName); File = SourceMgr.getFileManager().getFile(PathName); } } else { // Lookup for normal headers. llvm::sys::path::append(PathName, FileName); File = SourceMgr.getFileManager().getFile(PathName); // If this is a system module with a top-level header, this header // may have a counterpart (or replacement) in the set of headers // supplied by Clang. Find that builtin header. if (ActiveModule->IsSystem && !Umbrella && BuiltinIncludeDir && BuiltinIncludeDir != Directory && isBuiltinHeader(FileName)) { SmallString<128> BuiltinPathName(BuiltinIncludeDir->getName()); llvm::sys::path::append(BuiltinPathName, FileName); BuiltinFile = SourceMgr.getFileManager().getFile(BuiltinPathName); // If Clang supplies this header but the underlying system does not, // just silently swap in our builtin version. Otherwise, we'll end // up adding both (later). if (!File && BuiltinFile) { File = BuiltinFile; BuiltinFile = 0; } } } } // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. // Come up with a lazy way to do this. if (File) { if (const Module *OwningModule = Map.Headers[File]) { Diags.Report(FileNameLoc, diag::err_mmap_header_conflict) << FileName << OwningModule->getFullModuleName(); HadError = true; } else if (Umbrella) { const DirectoryEntry *UmbrellaDir = File->getDir(); if ((OwningModule = Map.UmbrellaDirs[UmbrellaDir])) { Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash) << OwningModule->getFullModuleName(); HadError = true; } else { // Record this umbrella header. Map.setUmbrellaHeader(ActiveModule, File); } } else { // Record this header. Map.addHeader(ActiveModule, File); // If there is a builtin counterpart to this file, add it now. if (BuiltinFile) Map.addHeader(ActiveModule, BuiltinFile); } } else { Diags.Report(FileNameLoc, diag::err_mmap_header_not_found) << Umbrella << FileName; HadError = true; } }
static enum CXChildVisitResult findFileIdRefVisit(CXCursor cursor, CXCursor parent, CXClientData client_data) { CXCursor declCursor = clang_getCursorReferenced(cursor); if (!clang_isDeclaration(declCursor.kind)) return CXChildVisit_Recurse; const Decl *D = cxcursor::getCursorDecl(declCursor); if (!D) return CXChildVisit_Continue; FindFileIdRefVisitData *data = (FindFileIdRefVisitData *)client_data; if (data->isHit(D)) { cursor = cxcursor::getSelectorIdentifierCursor(data->SelectorIdIdx, cursor); // We are looking for identifiers to highlight so for objc methods (and // not a parameter) we can only highlight the selector identifiers. if ((cursor.kind == CXCursor_ObjCClassMethodDecl || cursor.kind == CXCursor_ObjCInstanceMethodDecl) && cxcursor::getSelectorIdentifierIndex(cursor) == -1) return CXChildVisit_Recurse; if (clang_isExpression(cursor.kind)) { if (cursor.kind == CXCursor_DeclRefExpr || cursor.kind == CXCursor_MemberRefExpr) { // continue.. } else if (cursor.kind == CXCursor_ObjCMessageExpr && cxcursor::getSelectorIdentifierIndex(cursor) != -1) { // continue.. } else return CXChildVisit_Recurse; } SourceLocation Loc = cxloc::translateSourceLocation(clang_getCursorLocation(cursor)); SourceLocation SelIdLoc = cxcursor::getSelectorIdentifierLoc(cursor); if (SelIdLoc.isValid()) Loc = SelIdLoc; ASTContext &Ctx = data->getASTContext(); SourceManager &SM = Ctx.getSourceManager(); bool isInMacroDef = false; if (Loc.isMacroID()) { bool isMacroArg; Loc = getFileSpellingLoc(SM, Loc, isMacroArg); isInMacroDef = !isMacroArg; } // We are looking for identifiers in a specific file. std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc); if (LocInfo.first != data->FID) return CXChildVisit_Recurse; if (isInMacroDef) { // FIXME: For a macro definition make sure that all expansions // of it expand to the same reference before allowing to point to it. return CXChildVisit_Recurse; } if (data->visitor.visit(data->visitor.context, cursor, cxloc::translateSourceRange(Ctx, Loc)) == CXVisit_Break) return CXChildVisit_Break; } return CXChildVisit_Recurse; }
/// CheckExceptionSpecSubset - Check whether the second function type's /// exception specification is a subset (or equivalent) of the first function /// type. This is used by override and pointer assignment checks. bool Sema::CheckExceptionSpecSubset( const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID, const FunctionProtoType *Superset, SourceLocation SuperLoc, const FunctionProtoType *Subset, SourceLocation SubLoc) { // Just auto-succeed under -fno-exceptions. if (!getLangOptions().Exceptions) return false; // FIXME: As usual, we could be more specific in our error messages, but // that better waits until we've got types with source locations. if (!SubLoc.isValid()) SubLoc = SuperLoc; // If superset contains everything, we're done. if (!Superset->hasExceptionSpec() || Superset->hasAnyExceptionSpec()) return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc); // It does not. If the subset contains everything, we've failed. if (!Subset->hasExceptionSpec() || Subset->hasAnyExceptionSpec()) { Diag(SubLoc, DiagID); if (NoteID.getDiagID() != 0) Diag(SuperLoc, NoteID); return true; } // Neither contains everything. Do a proper comparison. for (FunctionProtoType::exception_iterator SubI = Subset->exception_begin(), SubE = Subset->exception_end(); SubI != SubE; ++SubI) { // Take one type from the subset. QualType CanonicalSubT = Context.getCanonicalType(*SubI); // Unwrap pointers and references so that we can do checks within a class // hierarchy. Don't unwrap member pointers; they don't have hierarchy // conversions on the pointee. bool SubIsPointer = false; if (const ReferenceType *RefTy = CanonicalSubT->getAs<ReferenceType>()) CanonicalSubT = RefTy->getPointeeType(); if (const PointerType *PtrTy = CanonicalSubT->getAs<PointerType>()) { CanonicalSubT = PtrTy->getPointeeType(); SubIsPointer = true; } bool SubIsClass = CanonicalSubT->isRecordType(); CanonicalSubT = CanonicalSubT.getLocalUnqualifiedType(); CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, /*DetectVirtual=*/false); bool Contained = false; // Make sure it's in the superset. for (FunctionProtoType::exception_iterator SuperI = Superset->exception_begin(), SuperE = Superset->exception_end(); SuperI != SuperE; ++SuperI) { QualType CanonicalSuperT = Context.getCanonicalType(*SuperI); // SubT must be SuperT or derived from it, or pointer or reference to // such types. if (const ReferenceType *RefTy = CanonicalSuperT->getAs<ReferenceType>()) CanonicalSuperT = RefTy->getPointeeType(); if (SubIsPointer) { if (const PointerType *PtrTy = CanonicalSuperT->getAs<PointerType>()) CanonicalSuperT = PtrTy->getPointeeType(); else { continue; } } CanonicalSuperT = CanonicalSuperT.getLocalUnqualifiedType(); // If the types are the same, move on to the next type in the subset. if (CanonicalSubT == CanonicalSuperT) { Contained = true; break; } // Otherwise we need to check the inheritance. if (!SubIsClass || !CanonicalSuperT->isRecordType()) continue; Paths.clear(); if (!IsDerivedFrom(CanonicalSubT, CanonicalSuperT, Paths)) continue; if (Paths.isAmbiguous(Context.getCanonicalType(CanonicalSuperT))) continue; // Do this check from a context without privileges. switch (CheckBaseClassAccess(SourceLocation(), CanonicalSuperT, CanonicalSubT, Paths.front(), /*Diagnostic*/ 0, /*ForceCheck*/ true, /*ForceUnprivileged*/ true)) { case AR_accessible: break; case AR_inaccessible: continue; case AR_dependent: llvm_unreachable("access check dependent for unprivileged context"); break; case AR_delayed: llvm_unreachable("access check delayed in non-declaration"); break; } Contained = true; break; } if (!Contained) { Diag(SubLoc, DiagID); if (NoteID.getDiagID() != 0) Diag(SuperLoc, NoteID); return true; } } // We've run half the gauntlet. return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc); }
void UseOverride::check(const MatchFinder::MatchResult &Result) { const FunctionDecl *Method = Result.Nodes.getStmtAs<FunctionDecl>("method"); const SourceManager &Sources = *Result.SourceManager; assert(Method != nullptr); if (Method->getInstantiatedFromMemberFunction() != nullptr) Method = Method->getInstantiatedFromMemberFunction(); if (Method->isImplicit() || Method->getLocation().isMacroID() || Method->isOutOfLine()) return; bool HasVirtual = Method->isVirtualAsWritten(); bool HasOverride = Method->getAttr<OverrideAttr>(); bool HasFinal = Method->getAttr<FinalAttr>(); bool OnlyVirtualSpecified = HasVirtual && !HasOverride && !HasFinal; unsigned KeywordCount = HasVirtual + HasOverride + HasFinal; if (!OnlyVirtualSpecified && KeywordCount == 1) return; // Nothing to do. DiagnosticBuilder Diag = diag( Method->getLocation(), OnlyVirtualSpecified ? "Prefer using 'override' or 'final' instead of 'virtual'" : "Use exactly one of 'virtual', 'override' or (rarely) 'final'"); CharSourceRange FileRange = Lexer::makeFileCharRange( CharSourceRange::getTokenRange(Method->getSourceRange()), Sources, Result.Context->getLangOpts()); if (!FileRange.isValid()) return; // FIXME: Instead of re-lexing and looking for specific macros such as // 'ABSTRACT', properly store the location of 'virtual' and '= 0' in each // FunctionDecl. SmallVector<Token, 16> Tokens = ParseTokens(FileRange, Sources, Result.Context->getLangOpts()); // Add 'override' on inline declarations that don't already have it. if (!HasFinal && !HasOverride) { SourceLocation InsertLoc; StringRef ReplacementText = "override "; if (Method->hasAttrs()) { for (const clang::Attr *A : Method->getAttrs()) { if (!A->isImplicit()) { InsertLoc = Sources.getExpansionLoc(A->getLocation()); break; } } } if (InsertLoc.isInvalid() && Method->doesThisDeclarationHaveABody() && Method->getBody() && !Method->isDefaulted()) InsertLoc = Method->getBody()->getLocStart(); if (!InsertLoc.isValid()) { if (Tokens.size() > 2 && GetText(Tokens.back(), Sources) == "0" && GetText(Tokens[Tokens.size() - 2], Sources) == "=") { InsertLoc = Tokens[Tokens.size() - 2].getLocation(); } else if (GetText(Tokens.back(), Sources) == "ABSTRACT") { InsertLoc = Tokens.back().getLocation(); } } if (!InsertLoc.isValid()) { InsertLoc = FileRange.getEnd(); ReplacementText = " override"; } Diag << FixItHint::CreateInsertion(InsertLoc, ReplacementText); } if (HasFinal && HasOverride) { SourceLocation OverrideLoc = Method->getAttr<OverrideAttr>()->getLocation(); Diag << FixItHint::CreateRemoval( CharSourceRange::getTokenRange(OverrideLoc, OverrideLoc)); } if (Method->isVirtualAsWritten()) { for (Token Tok : Tokens) { if (Tok.is(tok::raw_identifier) && GetText(Tok, Sources) == "virtual") { Diag << FixItHint::CreateRemoval(CharSourceRange::getTokenRange( Tok.getLocation(), Tok.getLocation())); break; } } } }
/// EvaluateDefined - Process a 'defined(sym)' expression. static bool EvaluateDefined(PPValue &Result, Token &PeekTok, DefinedTracker &DT, bool ValueLive, Preprocessor &PP) { SourceLocation beginLoc(PeekTok.getLocation()); Result.setBegin(beginLoc); // Get the next token, don't expand it. PP.LexUnexpandedNonComment(PeekTok); // Two options, it can either be a pp-identifier or a (. SourceLocation LParenLoc; if (PeekTok.is(tok::l_paren)) { // Found a paren, remember we saw it and skip it. LParenLoc = PeekTok.getLocation(); PP.LexUnexpandedNonComment(PeekTok); } if (PeekTok.is(tok::code_completion)) { if (PP.getCodeCompletionHandler()) PP.getCodeCompletionHandler()->CodeCompleteMacroName(false); PP.setCodeCompletionReached(); PP.LexUnexpandedNonComment(PeekTok); } // If we don't have a pp-identifier now, this is an error. if (PP.CheckMacroName(PeekTok, MU_Other)) return true; // Otherwise, we got an identifier, is it defined to something? IdentifierInfo *II = PeekTok.getIdentifierInfo(); MacroDefinition Macro = PP.getMacroDefinition(II); Result.Val = !!Macro; Result.Val.setIsUnsigned(false); // Result is signed intmax_t. // If there is a macro, mark it used. if (Result.Val != 0 && ValueLive) PP.markMacroAsUsed(Macro.getMacroInfo()); // Save macro token for callback. Token macroToken(PeekTok); // If we are in parens, ensure we have a trailing ). if (LParenLoc.isValid()) { // Consume identifier. Result.setEnd(PeekTok.getLocation()); PP.LexUnexpandedNonComment(PeekTok); if (PeekTok.isNot(tok::r_paren)) { PP.Diag(PeekTok.getLocation(), diag::err_pp_expected_after) << "'defined'" << tok::r_paren; PP.Diag(LParenLoc, diag::note_matching) << tok::l_paren; return true; } // Consume the ). Result.setEnd(PeekTok.getLocation()); PP.LexNonComment(PeekTok); } else { // Consume identifier. Result.setEnd(PeekTok.getLocation()); PP.LexNonComment(PeekTok); } // Invoke the 'defined' callback. if (PPCallbacks *Callbacks = PP.getPPCallbacks()) { Callbacks->Defined(macroToken, Macro, SourceRange(beginLoc, PeekTok.getLocation())); } // Success, remember that we saw defined(X). DT.State = DefinedTracker::DefinedMacro; DT.TheMacro = II; return false; }
// #pragma unused(identifier) void PragmaUnusedHandler::HandlePragma(Preprocessor &PP, Token &UnusedTok) { // FIXME: Should we be expanding macros here? My guess is no. SourceLocation UnusedLoc = UnusedTok.getLocation(); // Lex the left '('. Token Tok; PP.Lex(Tok); if (Tok.isNot(tok::l_paren)) { PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused"; return; } SourceLocation LParenLoc = Tok.getLocation(); // Lex the declaration reference(s). llvm::SmallVector<Action::ExprTy*, 5> Ex; SourceLocation RParenLoc; bool LexID = true; while (true) { PP.Lex(Tok); if (LexID) { if (Tok.is(tok::identifier)) { Action::OwningExprResult Name = Actions.ActOnIdentifierExpr(parser.CurScope, Tok.getLocation(), *Tok.getIdentifierInfo(), false); if (Name.isInvalid()) { if (!Ex.empty()) Action::MultiExprArg Release(Actions, &Ex[0], Ex.size()); return; } Ex.push_back(Name.release()); LexID = false; continue; } // Illegal token! Release the parsed expressions (if any) and emit // a warning. if (!Ex.empty()) Action::MultiExprArg Release(Actions, &Ex[0], Ex.size()); PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var); return; } // We are execting a ')' or a ','. if (Tok.is(tok::comma)) { LexID = true; continue; } if (Tok.is(tok::r_paren)) { RParenLoc = Tok.getLocation(); break; } // Illegal token! Release the parsed expressions (if any) and emit // a warning. if (!Ex.empty()) Action::MultiExprArg Release(Actions, &Ex[0], Ex.size()); PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc); return; } // Verify that we have a location for the right parenthesis. assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'"); assert(!Ex.empty() && "Valid '#pragma unused' must have arguments"); // Perform the action to handle the pragma. Actions.ActOnPragmaUnused(&Ex[0], Ex.size(), UnusedLoc, LParenLoc, RParenLoc); }
/// EvaluateDefined - Process a 'defined(sym)' expression. static bool EvaluateDefined(PPValue &Result, Token &PeekTok, DefinedTracker &DT, bool ValueLive, Preprocessor &PP) { SourceLocation beginLoc(PeekTok.getLocation()); Result.setBegin(beginLoc); // Get the next token, don't expand it. PP.LexUnexpandedNonComment(PeekTok); // Two options, it can either be a pp-identifier or a (. SourceLocation LParenLoc; if (PeekTok.is(tok::l_paren)) { // Found a paren, remember we saw it and skip it. LParenLoc = PeekTok.getLocation(); PP.LexUnexpandedNonComment(PeekTok); } if (PeekTok.is(tok::code_completion)) { if (PP.getCodeCompletionHandler()) PP.getCodeCompletionHandler()->CodeCompleteMacroName(false); PP.setCodeCompletionReached(); PP.LexUnexpandedNonComment(PeekTok); } // If we don't have a pp-identifier now, this is an error. if (PP.CheckMacroName(PeekTok, MU_Other)) return true; // Otherwise, we got an identifier, is it defined to something? IdentifierInfo *II = PeekTok.getIdentifierInfo(); MacroDefinition Macro = PP.getMacroDefinition(II); Result.Val = !!Macro; Result.Val.setIsUnsigned(false); // Result is signed intmax_t. // If there is a macro, mark it used. if (Result.Val != 0 && ValueLive) PP.markMacroAsUsed(Macro.getMacroInfo()); // Save macro token for callback. Token macroToken(PeekTok); // If we are in parens, ensure we have a trailing ). if (LParenLoc.isValid()) { // Consume identifier. Result.setEnd(PeekTok.getLocation()); PP.LexUnexpandedNonComment(PeekTok); if (PeekTok.isNot(tok::r_paren)) { PP.Diag(PeekTok.getLocation(), diag::err_pp_expected_after) << "'defined'" << tok::r_paren; PP.Diag(LParenLoc, diag::note_matching) << tok::l_paren; return true; } // Consume the ). Result.setEnd(PeekTok.getLocation()); PP.LexNonComment(PeekTok); } else { // Consume identifier. Result.setEnd(PeekTok.getLocation()); PP.LexNonComment(PeekTok); } // [cpp.cond]p4: // Prior to evaluation, macro invocations in the list of preprocessing // tokens that will become the controlling constant expression are replaced // (except for those macro names modified by the 'defined' unary operator), // just as in normal text. If the token 'defined' is generated as a result // of this replacement process or use of the 'defined' unary operator does // not match one of the two specified forms prior to macro replacement, the // behavior is undefined. // This isn't an idle threat, consider this program: // #define FOO // #define BAR defined(FOO) // #if BAR // ... // #else // ... // #endif // clang and gcc will pick the #if branch while Visual Studio will take the // #else branch. Emit a warning about this undefined behavior. if (beginLoc.isMacroID()) { bool IsFunctionTypeMacro = PP.getSourceManager() .getSLocEntry(PP.getSourceManager().getFileID(beginLoc)) .getExpansion() .isFunctionMacroExpansion(); // For object-type macros, it's easy to replace // #define FOO defined(BAR) // with // #if defined(BAR) // #define FOO 1 // #else // #define FOO 0 // #endif // and doing so makes sense since compilers handle this differently in // practice (see example further up). But for function-type macros, // there is no good way to write // # define FOO(x) (defined(M_ ## x) && M_ ## x) // in a different way, and compilers seem to agree on how to behave here. // So warn by default on object-type macros, but only warn in -pedantic // mode on function-type macros. if (IsFunctionTypeMacro) PP.Diag(beginLoc, diag::warn_defined_in_function_type_macro); else PP.Diag(beginLoc, diag::warn_defined_in_object_type_macro); } // Invoke the 'defined' callback. if (PPCallbacks *Callbacks = PP.getPPCallbacks()) { Callbacks->Defined(macroToken, Macro, SourceRange(beginLoc, PeekTok.getLocation())); } // Success, remember that we saw defined(X). DT.State = DefinedTracker::DefinedMacro; DT.TheMacro = II; return false; }
bool DeclExtractor::CheckTagDeclaration(TagDecl* NewTD, LookupResult& Previous){ // If the decl is already known invalid, don't check it. if (NewTD->isInvalidDecl()) return false; IdentifierInfo* Name = NewTD->getIdentifier(); // If this is not a definition, it must have a name. assert((Name != 0 || NewTD->isThisDeclarationADefinition()) && "Nameless record must be a definition!"); // Figure out the underlying type if this a enum declaration. We need to do // this early, because it's needed to detect if this is an incompatible // redeclaration. TagDecl::TagKind Kind = NewTD->getTagKind(); bool Invalid = false; assert(NewTD->getNumTemplateParameterLists() == 0 && "Cannot handle that yet!"); bool isExplicitSpecialization = false; if (Kind == TTK_Enum) { EnumDecl* ED = cast<EnumDecl>(NewTD); bool ScopedEnum = ED->isScoped(); const QualType QT = ED->getIntegerType(); if (QT.isNull() && ScopedEnum) // No underlying type explicitly specified, or we failed to parse the // type, default to int. ; //EnumUnderlying = m_Context->IntTy.getTypePtr(); else if (!QT.isNull()) { // C++0x 7.2p2: The type-specifier-seq of an enum-base shall name an // integral type; any cv-qualification is ignored. SourceLocation UnderlyingLoc; TypeSourceInfo* TI = 0; if ((TI = ED->getIntegerTypeSourceInfo())) UnderlyingLoc = TI->getTypeLoc().getBeginLoc(); if (!QT->isDependentType() && !QT->isIntegralType(*m_Context)) { m_Sema->Diag(UnderlyingLoc, diag::err_enum_invalid_underlying) << QT; } if (TI) m_Sema->DiagnoseUnexpandedParameterPack(UnderlyingLoc, TI, Sema::UPPC_FixedUnderlyingType); } } DeclContext *SearchDC = m_Sema->CurContext; DeclContext *DC = m_Sema->CurContext; //bool isStdBadAlloc = false; SourceLocation NameLoc = NewTD->getLocation(); // if (Name && SS.isNotEmpty()) { // // We have a nested-name tag ('struct foo::bar'). // // Check for invalid 'foo::'. // if (SS.isInvalid()) { // Name = 0; // goto CreateNewDecl; // } // // If this is a friend or a reference to a class in a dependent // // context, don't try to make a decl for it. // if (TUK == TUK_Friend || TUK == TUK_Reference) { // DC = computeDeclContext(SS, false); // if (!DC) { // IsDependent = true; // return 0; // } // } else { // DC = computeDeclContext(SS, true); // if (!DC) { // Diag(SS.getRange().getBegin(), // diag::err_dependent_nested_name_spec) // << SS.getRange(); // return 0; // } // } // if (RequireCompleteDeclContext(SS, DC)) // return 0; // SearchDC = DC; // // Look-up name inside 'foo::'. // LookupQualifiedName(Previous, DC); // if (Previous.isAmbiguous()) // return 0; // if (Previous.empty()) { // // Name lookup did not find anything. However, if the // // nested-name-specifier refers to the current instantiation, // // and that current instantiation has any dependent base // // classes, we might find something at instantiation time: treat // // this as a dependent elaborated-type-specifier. // // But this only makes any sense for reference-like lookups. // if (Previous.wasNotFoundInCurrentInstantiation() && // (TUK == TUK_Reference || TUK == TUK_Friend)) { // IsDependent = true; // return 0; // } // // A tag 'foo::bar' must already exist. // Diag(NameLoc, diag::err_not_tag_in_scope) // << Kind << Name << DC << SS.getRange(); // Name = 0; // Invalid = true; // goto CreateNewDecl; // } //} else if (Name) { // If this is a named struct, check to see if there was a previous forward // declaration or definition. // FIXME: We're looking into outer scopes here, even when we // shouldn't be. Doing so can result in ambiguities that we // shouldn't be diagnosing. //LookupName(Previous, S); if (Previous.isAmbiguous()) { LookupResult::Filter F = Previous.makeFilter(); while (F.hasNext()) { NamedDecl *ND = F.next(); if (ND->getDeclContext()->getRedeclContext() != SearchDC) F.erase(); } F.done(); } // Note: there used to be some attempt at recovery here. if (Previous.isAmbiguous()) { NewTD->setInvalidDecl(); return false; } if (!m_Sema->getLangOpts().CPlusPlus) { // FIXME: This makes sure that we ignore the contexts associated // with C structs, unions, and enums when looking for a matching // tag declaration or definition. See the similar lookup tweak // in Sema::LookupName; is there a better way to deal with this? while (isa<RecordDecl>(SearchDC) || isa<EnumDecl>(SearchDC)) SearchDC = SearchDC->getParent(); } } else if (m_Sema->getScopeForContext(m_Sema->CurContext) ->isFunctionPrototypeScope()) { // If this is an enum declaration in function prototype scope, set its // initial context to the translation unit. SearchDC = m_Context->getTranslationUnitDecl(); } if (Previous.isSingleResult() && Previous.getFoundDecl()->isTemplateParameter()) { // Maybe we will complain about the shadowed template parameter. m_Sema->DiagnoseTemplateParameterShadow(NameLoc, Previous.getFoundDecl()); // Just pretend that we didn't see the previous declaration. Previous.clear(); } if (m_Sema->getLangOpts().CPlusPlus && Name && DC && m_Sema->StdNamespace && DC->Equals(m_Sema->getStdNamespace()) && Name->isStr("bad_alloc")) { // This is a declaration of or a reference to "std::bad_alloc". //isStdBadAlloc = true; if (Previous.empty() && m_Sema->StdBadAlloc) { // std::bad_alloc has been implicitly declared (but made invisible to // name lookup). Fill in this implicit declaration as the previous // declaration, so that the declarations get chained appropriately. Previous.addDecl(m_Sema->getStdBadAlloc()); } } if (!Previous.empty()) { NamedDecl *PrevDecl = (*Previous.begin())->getUnderlyingDecl(); // It's okay to have a tag decl in the same scope as a typedef // which hides a tag decl in the same scope. Finding this // insanity with a redeclaration lookup can only actually happen // in C++. // // This is also okay for elaborated-type-specifiers, which is // technically forbidden by the current standard but which is // okay according to the likely resolution of an open issue; // see http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#407 if (m_Sema->getLangOpts().CPlusPlus) { if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(PrevDecl)) { if (const TagType *TT = TD->getUnderlyingType()->getAs<TagType>()) { TagDecl *Tag = TT->getDecl(); if (Tag->getDeclName() == Name && Tag->getDeclContext()->getRedeclContext() ->Equals(TD->getDeclContext()->getRedeclContext())) { PrevDecl = Tag; Previous.clear(); Previous.addDecl(Tag); Previous.resolveKind(); } } } } if (TagDecl *PrevTagDecl = dyn_cast<TagDecl>(PrevDecl)) { // If this is a use of a previous tag, or if the tag is already declared // in the same scope (so that the definition/declaration completes or // rementions the tag), reuse the decl. if (m_Sema->isDeclInScope(PrevDecl, SearchDC, m_Sema->getScopeForContext(m_Sema->CurContext), isExplicitSpecialization)) { // Make sure that this wasn't declared as an enum and now used as a // struct or something similar. SourceLocation KWLoc = NewTD->getLocStart(); if (!m_Sema->isAcceptableTagRedeclaration(PrevTagDecl, Kind, NewTD->isThisDeclarationADefinition(), KWLoc, *Name)) { bool SafeToContinue = (PrevTagDecl->getTagKind() != TTK_Enum && Kind != TTK_Enum); if (SafeToContinue) m_Sema->Diag(KWLoc, diag::err_use_with_wrong_tag) << Name << FixItHint::CreateReplacement(SourceRange(KWLoc), PrevTagDecl->getKindName()); else m_Sema->Diag(KWLoc, diag::err_use_with_wrong_tag) << Name; m_Sema->Diag(PrevTagDecl->getLocation(), diag::note_previous_use); if (SafeToContinue) Kind = PrevTagDecl->getTagKind(); else { // Recover by making this an anonymous redefinition. Name = 0; Previous.clear(); Invalid = true; } } if (Kind == TTK_Enum && PrevTagDecl->getTagKind() == TTK_Enum) { const EnumDecl *NewEnum = cast<EnumDecl>(NewTD); const EnumDecl *PrevEnum = cast<EnumDecl>(PrevTagDecl); // All conflicts with previous declarations are recovered by // returning the previous declaration. if (NewEnum->isScoped() != PrevEnum->isScoped()) { m_Sema->Diag(KWLoc, diag::err_enum_redeclare_scoped_mismatch) << PrevEnum->isScoped(); m_Sema->Diag(PrevTagDecl->getLocation(), diag::note_previous_use); NewTD->setInvalidDecl(); return false; } else if (PrevEnum->isFixed()) { QualType T = NewEnum->getIntegerType(); if (!m_Context->hasSameUnqualifiedType(T, PrevEnum->getIntegerType())) { m_Sema->Diag(NameLoc.isValid() ? NameLoc : KWLoc, diag::err_enum_redeclare_type_mismatch) << T << PrevEnum->getIntegerType(); m_Sema->Diag(PrevTagDecl->getLocation(), diag::note_previous_use); NewTD->setInvalidDecl(); return false; } } else if (NewEnum->isFixed() != PrevEnum->isFixed()) { m_Sema->Diag(KWLoc, diag::err_enum_redeclare_fixed_mismatch) << PrevEnum->isFixed(); m_Sema->Diag(PrevTagDecl->getLocation(), diag::note_previous_use); NewTD->setInvalidDecl(); return false; } } if (!Invalid) { // If this is a use, just return the declaration we found. // Diagnose attempts to redefine a tag. if (NewTD->isThisDeclarationADefinition()) { if (TagDecl* Def = PrevTagDecl->getDefinition()) { // If we're defining a specialization and the previous // definition is from an implicit instantiation, don't emit an // error here; we'll catch this in the general case below. if (!isExplicitSpecialization || !isa<CXXRecordDecl>(Def) || cast<CXXRecordDecl>(Def)->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) { m_Sema->Diag(NameLoc, diag::err_redefinition) << Name; m_Sema->Diag(Def->getLocation(), diag::note_previous_definition); // If this is a redefinition, recover by making this // struct be anonymous, which will make any later // references get the previous definition. Name = 0; Previous.clear(); Invalid = true; } } else { // If the type is currently being defined, complain // about a nested redefinition. const TagType *Tag = cast<TagType>(m_Context->getTagDeclType(PrevTagDecl)); if (Tag->isBeingDefined()) { m_Sema->Diag(NameLoc, diag::err_nested_redefinition) << Name; m_Sema->Diag(PrevTagDecl->getLocation(), diag::note_previous_definition); Name = 0; Previous.clear(); Invalid = true; } } // Okay, this is definition of a previously declared or referenced // tag PrevDecl. We're going to create a new Decl for it. } } // If we get here we have (another) forward declaration or we // have a definition. Just create a new decl. } else { // If we get here, this is a definition of a new tag type in a nested // scope, e.g. "struct foo; void bar() { struct foo; }", just create a // new decl/type. We set PrevDecl to NULL so that the entities // have distinct types. Previous.clear(); } // If we get here, we're going to create a new Decl. If PrevDecl // is non-NULL, it's a definition of the tag declared by // PrevDecl. If it's NULL, we have a new definition. // Otherwise, PrevDecl is not a tag, but was found with tag // lookup. This is only actually possible in C++, where a few // things like templates still live in the tag namespace. } else { assert(m_Sema->getLangOpts().CPlusPlus); // Diagnose if the declaration is in scope. if (!m_Sema->isDeclInScope(PrevDecl, SearchDC, m_Sema->getScopeForContext(m_Sema->CurContext), isExplicitSpecialization)) { // do nothing // Otherwise it's a declaration. Call out a particularly common // case here. } else if (TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(PrevDecl)) { unsigned Kind = 0; if (isa<TypeAliasDecl>(PrevDecl)) Kind = 1; m_Sema->Diag(NameLoc, diag::err_tag_definition_of_typedef) << Name << Kind << TND->getUnderlyingType(); m_Sema->Diag(PrevDecl->getLocation(), diag::note_previous_decl) << PrevDecl; Invalid = true; // Otherwise, diagnose. } else { // The tag name clashes with something else in the target scope, // issue an error and recover by making this tag be anonymous. m_Sema->Diag(NameLoc, diag::err_redefinition_different_kind) << Name; m_Sema->Diag(PrevDecl->getLocation(), diag::note_previous_definition); Name = 0; Invalid = true; } // The existing declaration isn't relevant to us; we're in a // new scope, so clear out the previous declaration. Previous.clear(); } } if (Invalid) { NewTD->setInvalidDecl(); return false; } return true; }
/// \brief Parse a C++ template template argument. ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() { if (!Tok.is(tok::identifier) && !Tok.is(tok::coloncolon) && !Tok.is(tok::annot_cxxscope)) return ParsedTemplateArgument(); // C++0x [temp.arg.template]p1: // A template-argument for a template template-parameter shall be the name // of a class template or an alias template, expressed as id-expression. // // We parse an id-expression that refers to a class template or alias // template. The grammar we parse is: // // nested-name-specifier[opt] template[opt] identifier ...[opt] // // followed by a token that terminates a template argument, such as ',', // '>', or (in some cases) '>>'. CXXScopeSpec SS; // nested-name-specifier, if present ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false); ParsedTemplateArgument Result; SourceLocation EllipsisLoc; if (SS.isSet() && Tok.is(tok::kw_template)) { // Parse the optional 'template' keyword following the // nested-name-specifier. SourceLocation TemplateKWLoc = ConsumeToken(); if (Tok.is(tok::identifier)) { // We appear to have a dependent template name. UnqualifiedId Name; Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation()); ConsumeToken(); // the identifier // Parse the ellipsis. if (Tok.is(tok::ellipsis)) EllipsisLoc = ConsumeToken(); // If the next token signals the end of a template argument, // then we have a dependent template name that could be a template // template argument. TemplateTy Template; if (isEndOfTemplateArgument(Tok) && Actions.ActOnDependentTemplateName(getCurScope(), SS, TemplateKWLoc, Name, /*ObjectType=*/ ParsedType(), /*EnteringContext=*/false, Template)) Result = ParsedTemplateArgument(SS, Template, Name.StartLocation); } } else if (Tok.is(tok::identifier)) { // We may have a (non-dependent) template name. TemplateTy Template; UnqualifiedId Name; Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation()); ConsumeToken(); // the identifier // Parse the ellipsis. if (Tok.is(tok::ellipsis)) EllipsisLoc = ConsumeToken(); if (isEndOfTemplateArgument(Tok)) { bool MemberOfUnknownSpecialization; TemplateNameKind TNK = Actions.isTemplateName(getCurScope(), SS, /*hasTemplateKeyword=*/false, Name, /*ObjectType=*/ ParsedType(), /*EnteringContext=*/false, Template, MemberOfUnknownSpecialization); if (TNK == TNK_Dependent_template_name || TNK == TNK_Type_template) { // We have an id-expression that refers to a class template or // (C++0x) alias template. Result = ParsedTemplateArgument(SS, Template, Name.StartLocation); } } } // If this is a pack expansion, build it as such. if (EllipsisLoc.isValid() && !Result.isInvalid()) Result = Actions.ActOnPackExpansion(Result, EllipsisLoc); return Result; }
// #pragma unused(identifier) void PragmaUnusedHandler::HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &UnusedTok) { // FIXME: Should we be expanding macros here? My guess is no. SourceLocation UnusedLoc = UnusedTok.getLocation(); // Lex the left '('. Token Tok; PP.Lex(Tok); if (Tok.isNot(tok::l_paren)) { PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused"; return; } // Lex the declaration reference(s). SmallVector<Token, 5> Identifiers; SourceLocation RParenLoc; bool LexID = true; while (true) { PP.Lex(Tok); if (LexID) { if (Tok.is(tok::identifier)) { Identifiers.push_back(Tok); LexID = false; continue; } // Illegal token! PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var); return; } // We are execting a ')' or a ','. if (Tok.is(tok::comma)) { LexID = true; continue; } if (Tok.is(tok::r_paren)) { RParenLoc = Tok.getLocation(); break; } // Illegal token! PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc); return; } PP.Lex(Tok); if (Tok.isNot(tok::eod)) { PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "unused"; return; } // Verify that we have a location for the right parenthesis. assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'"); assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments"); // For each identifier token, insert into the token stream a // annot_pragma_unused token followed by the identifier token. // This allows us to cache a "#pragma unused" that occurs inside an inline // C++ member function. Token *Toks = new Token[2*Identifiers.size()]; for (unsigned i=0; i != Identifiers.size(); i++) { Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1]; pragmaUnusedTok.startToken(); pragmaUnusedTok.setKind(tok::annot_pragma_unused); pragmaUnusedTok.setLocation(UnusedLoc); idTok = Identifiers[i]; } PP.EnterTokenStream(Toks, 2*Identifiers.size(), /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true); }
StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, bool IsVolatile, unsigned NumOutputs, unsigned NumInputs, IdentifierInfo **Names, MultiExprArg constraints, MultiExprArg Exprs, Expr *asmString, MultiExprArg clobbers, SourceLocation RParenLoc) { unsigned NumClobbers = clobbers.size(); StringLiteral **Constraints = reinterpret_cast<StringLiteral**>(constraints.data()); StringLiteral *AsmString = cast<StringLiteral>(asmString); StringLiteral **Clobbers = reinterpret_cast<StringLiteral**>(clobbers.data()); SmallVector<TargetInfo::ConstraintInfo, 4> OutputConstraintInfos; // The parser verifies that there is a string literal here. assert(AsmString->isAscii()); // If we're compiling CUDA file and function attributes indicate that it's not // for this compilation side, skip all the checks. if (!DeclAttrsMatchCUDAMode(getLangOpts(), getCurFunctionDecl())) { GCCAsmStmt *NS = new (Context) GCCAsmStmt( Context, AsmLoc, IsSimple, IsVolatile, NumOutputs, NumInputs, Names, Constraints, Exprs.data(), AsmString, NumClobbers, Clobbers, RParenLoc); return NS; } // If we're compiling HCC file and function attributes indicate that it's not // for this compilation side, skip all the checks. if (!DeclAttrsMatchHCCMode(getLangOpts(), getCurFunctionDecl())) { GCCAsmStmt *NS = new (Context) GCCAsmStmt( Context, AsmLoc, IsSimple, IsVolatile, NumOutputs, NumInputs, Names, Constraints, Exprs.data(), AsmString, NumClobbers, Clobbers, RParenLoc); return NS; } for (unsigned i = 0; i != NumOutputs; i++) { StringLiteral *Literal = Constraints[i]; assert(Literal->isAscii()); 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()); ExprResult ER = CheckPlaceholderExpr(Exprs[i]); if (ER.isInvalid()) return StmtError(); Exprs[i] = ER.get(); // Check that the output exprs are valid lvalues. Expr *OutputExpr = Exprs[i]; // Referring to parameters is not allowed in naked functions. if (CheckNakedParmReference(OutputExpr, *this)) return StmtError(); // Check that the output expression is compatible with memory constraint. if (Info.allowsMemory() && checkExprMemoryConstraintCompat(*this, OutputExpr, Info, false)) return StmtError(); OutputConstraintInfos.push_back(Info); // If this is dependent, just continue. if (OutputExpr->isTypeDependent()) continue; Expr::isModifiableLvalueResult IsLV = OutputExpr->isModifiableLvalue(Context, /*Loc=*/nullptr); switch (IsLV) { case Expr::MLV_Valid: // Cool, this is an lvalue. break; case Expr::MLV_ArrayType: // This is OK too. break; case Expr::MLV_LValueCast: { const Expr *LVal = OutputExpr->IgnoreParenNoopCasts(Context); if (!getLangOpts().HeinousExtensions) { Diag(LVal->getLocStart(), diag::err_invalid_asm_cast_lvalue) << OutputExpr->getSourceRange(); } else { Diag(LVal->getLocStart(), diag::warn_invalid_asm_cast_lvalue) << OutputExpr->getSourceRange(); } // Accept, even if we emitted an error diagnostic. break; } case Expr::MLV_IncompleteType: case Expr::MLV_IncompleteVoidType: if (RequireCompleteType(OutputExpr->getLocStart(), Exprs[i]->getType(), diag::err_dereference_incomplete_type)) return StmtError(); default: return StmtError(Diag(OutputExpr->getLocStart(), diag::err_asm_invalid_lvalue_in_output) << OutputExpr->getSourceRange()); } unsigned Size = Context.getTypeSize(OutputExpr->getType()); if (!Context.getTargetInfo().validateOutputSize(Literal->getString(), Size)) return StmtError(Diag(OutputExpr->getLocStart(), diag::err_asm_invalid_output_size) << Info.getConstraintStr()); } SmallVector<TargetInfo::ConstraintInfo, 4> InputConstraintInfos; for (unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) { StringLiteral *Literal = Constraints[i]; assert(Literal->isAscii()); StringRef InputName; if (Names[i]) InputName = Names[i]->getName(); TargetInfo::ConstraintInfo Info(Literal->getString(), InputName); if (!Context.getTargetInfo().validateInputConstraint(OutputConstraintInfos, Info)) { return StmtError(Diag(Literal->getLocStart(), diag::err_asm_invalid_input_constraint) << Info.getConstraintStr()); } ExprResult ER = CheckPlaceholderExpr(Exprs[i]); if (ER.isInvalid()) return StmtError(); Exprs[i] = ER.get(); Expr *InputExpr = Exprs[i]; // Referring to parameters is not allowed in naked functions. if (CheckNakedParmReference(InputExpr, *this)) return StmtError(); // Check that the input expression is compatible with memory constraint. if (Info.allowsMemory() && checkExprMemoryConstraintCompat(*this, InputExpr, Info, true)) return StmtError(); // 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()); } else if (Info.requiresImmediateConstant() && !Info.allowsRegister()) { if (!InputExpr->isValueDependent()) { llvm::APSInt Result; if (!InputExpr->EvaluateAsInt(Result, Context)) return StmtError( Diag(InputExpr->getLocStart(), diag::err_asm_immediate_expected) << Info.getConstraintStr() << InputExpr->getSourceRange()); if (!Info.isValidAsmImmediate(Result)) return StmtError(Diag(InputExpr->getLocStart(), diag::err_invalid_asm_value_for_constraint) << Result.toString(10) << Info.getConstraintStr() << InputExpr->getSourceRange()); } } else { ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]); if (Result.isInvalid()) return StmtError(); Exprs[i] = Result.get(); } 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()); } } InputConstraintInfos.push_back(Info); const Type *Ty = Exprs[i]->getType().getTypePtr(); if (Ty->isDependentType()) continue; if (!Ty->isVoidType() || !Info.allowsMemory()) if (RequireCompleteType(InputExpr->getLocStart(), Exprs[i]->getType(), diag::err_dereference_incomplete_type)) return StmtError(); unsigned Size = Context.getTypeSize(Ty); if (!Context.getTargetInfo().validateInputSize(Literal->getString(), Size)) return StmtError(Diag(InputExpr->getLocStart(), diag::err_asm_invalid_input_size) << Info.getConstraintStr()); } // Check that the clobbers are valid. for (unsigned i = 0; i != NumClobbers; i++) { StringLiteral *Literal = Clobbers[i]; assert(Literal->isAscii()); StringRef Clobber = Literal->getString(); if (!Context.getTargetInfo().isValidClobber(Clobber)) return StmtError(Diag(Literal->getLocStart(), diag::err_asm_unknown_register_name) << Clobber); } GCCAsmStmt *NS = new (Context) GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs, NumInputs, Names, Constraints, Exprs.data(), AsmString, NumClobbers, Clobbers, RParenLoc); // Validate the asm string, ensuring it makes sense given the operands we // have. SmallVector<GCCAsmStmt::AsmStringPiece, 8> Pieces; unsigned DiagOffs; if (unsigned DiagID = NS->AnalyzeAsmString(Pieces, Context, DiagOffs)) { Diag(getLocationOfStringLiteralByte(AsmString, DiagOffs), DiagID) << AsmString->getSourceRange(); return StmtError(); } // Validate constraints and modifiers. for (unsigned i = 0, e = Pieces.size(); i != e; ++i) { GCCAsmStmt::AsmStringPiece &Piece = Pieces[i]; if (!Piece.isOperand()) continue; // Look for the correct constraint index. unsigned ConstraintIdx = Piece.getOperandNo(); unsigned NumOperands = NS->getNumOutputs() + NS->getNumInputs(); // Look for the (ConstraintIdx - NumOperands + 1)th constraint with // modifier '+'. if (ConstraintIdx >= NumOperands) { unsigned I = 0, E = NS->getNumOutputs(); for (unsigned Cnt = ConstraintIdx - NumOperands; I != E; ++I) if (OutputConstraintInfos[I].isReadWrite() && Cnt-- == 0) { ConstraintIdx = I; break; } assert(I != E && "Invalid operand number should have been caught in " " AnalyzeAsmString"); } // Now that we have the right indexes go ahead and check. StringLiteral *Literal = Constraints[ConstraintIdx]; const Type *Ty = Exprs[ConstraintIdx]->getType().getTypePtr(); if (Ty->isDependentType() || Ty->isIncompleteType()) continue; unsigned Size = Context.getTypeSize(Ty); std::string SuggestedModifier; if (!Context.getTargetInfo().validateConstraintModifier( Literal->getString(), Piece.getModifier(), Size, SuggestedModifier)) { Diag(Exprs[ConstraintIdx]->getLocStart(), diag::warn_asm_mismatched_size_modifier); if (!SuggestedModifier.empty()) { auto B = Diag(Piece.getRange().getBegin(), diag::note_asm_missing_constraint_modifier) << SuggestedModifier; SuggestedModifier = "%" + SuggestedModifier + Piece.getString(); B.AddFixItHint(FixItHint::CreateReplacement(Piece.getRange(), SuggestedModifier)); } } } // Validate tied input operands for type mismatches. unsigned NumAlternatives = ~0U; for (unsigned i = 0, e = OutputConstraintInfos.size(); i != e; ++i) { TargetInfo::ConstraintInfo &Info = OutputConstraintInfos[i]; StringRef ConstraintStr = Info.getConstraintStr(); unsigned AltCount = ConstraintStr.count(',') + 1; if (NumAlternatives == ~0U) NumAlternatives = AltCount; else if (NumAlternatives != AltCount) return StmtError(Diag(NS->getOutputExpr(i)->getLocStart(), diag::err_asm_unexpected_constraint_alternatives) << NumAlternatives << AltCount); } SmallVector<size_t, 4> InputMatchedToOutput(OutputConstraintInfos.size(), ~0U); for (unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) { TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i]; StringRef ConstraintStr = Info.getConstraintStr(); unsigned AltCount = ConstraintStr.count(',') + 1; if (NumAlternatives == ~0U) NumAlternatives = AltCount; else if (NumAlternatives != AltCount) return StmtError(Diag(NS->getInputExpr(i)->getLocStart(), diag::err_asm_unexpected_constraint_alternatives) << NumAlternatives << AltCount); // 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]; // Make sure no more than one input constraint matches each output. assert(TiedTo < InputMatchedToOutput.size() && "TiedTo value out of range"); if (InputMatchedToOutput[TiedTo] != ~0U) { Diag(NS->getInputExpr(i)->getLocStart(), diag::err_asm_input_duplicate_match) << TiedTo; Diag(NS->getInputExpr(InputMatchedToOutput[TiedTo])->getLocStart(), diag::note_asm_input_duplicate_first) << TiedTo; return StmtError(); } InputMatchedToOutput[TiedTo] = i; 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).get(); 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(); } // Check for conflicts between clobber list and input or output lists SourceLocation ConstraintLoc = getClobberConflictLocation(Exprs, Constraints, Clobbers, NumClobbers, Context.getTargetInfo(), Context); if (ConstraintLoc.isValid()) return Diag(ConstraintLoc, diag::error_inoutput_conflict_with_clobber); return NS; }
void TypeRenameTransform::processFunctionDecl(FunctionDecl *D) { // if no type source info, it's a void f(void) function auto TSI = D->getTypeSourceInfo(); if (TSI) { processTypeLoc(TSI->getTypeLoc()); } // handle ctor name initializers if (auto CD = dyn_cast<CXXConstructorDecl>(D)) { auto BL = CD->getLocation(); std::string newName; if (BL.isValid() && CD->getParent()->getLocation() != BL && nameMatches(CD->getParent(), newName, true)) { renameLocation(BL, newName); } for (auto II = CD->init_begin(), IE = CD->init_end(); II != IE; ++II) { if ((*II)->isBaseInitializer()) { processTypeLoc((*II)->getBaseClassLoc()); } auto X = (*II)->getInit(); if (X) { processStmt(X); } } } // dtor if (auto DD = dyn_cast<CXXDestructorDecl>(D)) { // if parent matches auto BL = DD->getLocation(); std::string newName; auto P = DD->getParent(); if (BL.isValid() && P->getLocation() != BL && nameMatches(P, newName, true)) { // can't use renameLocation since this is a tricky case // need to use raw_identifier because Lexer::findLocationAfterToken // performs a raw lexing SourceLocation EL = Lexer::findLocationAfterToken(BL, tok::raw_identifier, sema->getSourceManager(), sema->getLangOpts(), false); // TODO: Find the right way to do this -- consider this a hack // llvm::errs() << indent() << "dtor at: " << loc(BL) << ", locStart: " << loc(DD->getLocStart()) // << ", nameAsString: " << P->getNameAsString() << ", len: " << P->getNameAsString().size() // << ", DD nameAsString: " << DD->getNameAsString() << ", len: " << DD->getNameAsString().size() // << "\n"; if (EL.isValid()) { // EL is 1 char after the dtor name ~Foo, so -1 == pos of 'o' SourceLocation NE = EL.getLocWithOffset(-1); // we use the parent's name to see how much we should back off // if we use D->getNameAsString(), we'd run into two problems: // (1) the name would be ~Foo // (2) the name for template class dtor would be ~Foo<T> SourceLocation NB = EL.getLocWithOffset(-(int)P->getNameAsString().size()); if (NB.isMacroID()) { // TODO: emit error llvm::errs() << "Warning: Token is resulted from macro expansion" " and is therefore not renamed, at: " << loc(NB) << "\n"; } else { // TODO: Determine if it's a wrtiable file // TODO: Determine if the location has already been touched or // needs skipping (such as in refactoring API user's code, then // the API headers need no changing since later the new API will be // in place) replace(SourceRange(NB, NE), newName); } } } } // rename the params' types for (auto PI = D->param_begin(), PE = D->param_end(); PI != PE; ++PI) { processParmVarDecl(*PI); } // the name itself processQualifierLoc(D->getQualifierLoc()); // handle body if (auto B = D->getBody()) { if (stmtInSameFileAsDecl(B, D)) { // llvm::errs() << indent() << "body? " << D->getBody() << "\n"; processStmt(B); } } }
bool MigrationContext::rewritePropertyAttribute(StringRef fromAttr, StringRef toAttr, SourceLocation atLoc) { if (atLoc.isMacroID()) return false; SourceManager &SM = Pass.Ctx.getSourceManager(); // Break down the source location. std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(atLoc); // Try to load the file buffer. bool invalidTemp = false; StringRef file = SM.getBufferData(locInfo.first, &invalidTemp); if (invalidTemp) return false; const char *tokenBegin = file.data() + locInfo.second; // Lex from the start of the given location. Lexer lexer(SM.getLocForStartOfFile(locInfo.first), Pass.Ctx.getLangOptions(), file.begin(), tokenBegin, file.end()); Token tok; lexer.LexFromRawLexer(tok); if (tok.isNot(tok::at)) return false; lexer.LexFromRawLexer(tok); if (tok.isNot(tok::raw_identifier)) return false; if (StringRef(tok.getRawIdentifierData(), tok.getLength()) != "property") return false; lexer.LexFromRawLexer(tok); if (tok.isNot(tok::l_paren)) return false; Token BeforeTok = tok; Token AfterTok; AfterTok.startToken(); SourceLocation AttrLoc; lexer.LexFromRawLexer(tok); if (tok.is(tok::r_paren)) return false; while (1) { if (tok.isNot(tok::raw_identifier)) return false; StringRef ident(tok.getRawIdentifierData(), tok.getLength()); if (ident == fromAttr) { if (!toAttr.empty()) { Pass.TA.replaceText(tok.getLocation(), fromAttr, toAttr); return true; } // We want to remove the attribute. AttrLoc = tok.getLocation(); } do { lexer.LexFromRawLexer(tok); if (AttrLoc.isValid() && AfterTok.is(tok::unknown)) AfterTok = tok; } while (tok.isNot(tok::comma) && tok.isNot(tok::r_paren)); if (tok.is(tok::r_paren)) break; if (AttrLoc.isInvalid()) BeforeTok = tok; lexer.LexFromRawLexer(tok); } if (toAttr.empty() && AttrLoc.isValid() && AfterTok.isNot(tok::unknown)) { // We want to remove the attribute. if (BeforeTok.is(tok::l_paren) && AfterTok.is(tok::r_paren)) { Pass.TA.remove(SourceRange(BeforeTok.getLocation(), AfterTok.getLocation())); } else if (BeforeTok.is(tok::l_paren) && AfterTok.is(tok::comma)) { Pass.TA.remove(SourceRange(AttrLoc, AfterTok.getLocation())); } else { Pass.TA.remove(SourceRange(BeforeTok.getLocation(), AttrLoc)); } return true; } return false; }
void CGDebugInfo::setLocation(SourceLocation Loc) { if (Loc.isValid()) CurLoc = M->getContext().getSourceManager().getInstantiationLoc(Loc); }
/// \brief This allows the client to specify that certain /// warnings are ignored. Notes can never be mapped, errors can only be /// mapped to fatal, and WARNINGs and EXTENSIONs can be mapped arbitrarily. /// /// \param The source location that this change of diagnostic state should /// take affect. It can be null if we are setting the latest state. void DiagnosticsEngine::setDiagnosticMapping(diag::kind Diag, diag::Mapping Map, SourceLocation L) { assert(Diag < diag::DIAG_UPPER_LIMIT && "Can only map builtin diagnostics"); assert((Diags->isBuiltinWarningOrExtension(Diag) || (Map == diag::MAP_FATAL || Map == diag::MAP_ERROR)) && "Cannot map errors into warnings!"); assert(!DiagStatePoints.empty()); bool isPragma = L.isValid(); FullSourceLoc Loc(L, *SourceMgr); FullSourceLoc LastStateChangePos = DiagStatePoints.back().Loc; DiagnosticMappingInfo MappingInfo = DiagnosticMappingInfo::Make( Map, /*IsUser=*/true, isPragma); // If this is a pragma mapping, then set the diagnostic mapping flags so that // we override command line options. if (isPragma) { MappingInfo.setNoWarningAsError(true); MappingInfo.setNoErrorAsFatal(true); } // Common case; setting all the diagnostics of a group in one place. if (Loc.isInvalid() || Loc == LastStateChangePos) { GetCurDiagState()->setMappingInfo(Diag, MappingInfo); return; } // Another common case; modifying diagnostic state in a source location // after the previous one. if ((Loc.isValid() && LastStateChangePos.isInvalid()) || LastStateChangePos.isBeforeInTranslationUnitThan(Loc)) { // A diagnostic pragma occurred, create a new DiagState initialized with // the current one and a new DiagStatePoint to record at which location // the new state became active. DiagStates.push_back(*GetCurDiagState()); PushDiagStatePoint(&DiagStates.back(), Loc); GetCurDiagState()->setMappingInfo(Diag, MappingInfo); return; } // We allow setting the diagnostic state in random source order for // completeness but it should not be actually happening in normal practice. DiagStatePointsTy::iterator Pos = GetDiagStatePointForLoc(Loc); assert(Pos != DiagStatePoints.end()); // Update all diagnostic states that are active after the given location. for (DiagStatePointsTy::iterator I = Pos+1, E = DiagStatePoints.end(); I != E; ++I) { GetCurDiagState()->setMappingInfo(Diag, MappingInfo); } // If the location corresponds to an existing point, just update its state. if (Pos->Loc == Loc) { GetCurDiagState()->setMappingInfo(Diag, MappingInfo); return; } // Create a new state/point and fit it into the vector of DiagStatePoints // so that the vector is always ordered according to location. Pos->Loc.isBeforeInTranslationUnitThan(Loc); DiagStates.push_back(*Pos->State); DiagState *NewState = &DiagStates.back(); GetCurDiagState()->setMappingInfo(Diag, MappingInfo); DiagStatePoints.insert(Pos+1, DiagStatePoint(NewState, FullSourceLoc(Loc, *SourceMgr))); }
/// \brief Based on the way the client configured the Diagnostic /// object, classify the specified diagnostic ID into a Level, consumable by /// the DiagnosticClient. /// /// \param Loc The source location we are interested in finding out the /// diagnostic state. Can be null in order to query the latest state. DiagnosticIDs::Level DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass, SourceLocation Loc, const Diagnostic &Diag, diag::Mapping *mapping) const { // Specific non-error diagnostics may be mapped to various levels from ignored // to error. Errors can only be mapped to fatal. DiagnosticIDs::Level Result = DiagnosticIDs::Fatal; Diagnostic::DiagStatePointsTy::iterator Pos = Diag.GetDiagStatePointForLoc(Loc); Diagnostic::DiagState *State = Pos->State; // Get the mapping information, if unset, compute it lazily. unsigned MappingInfo = Diag.getDiagnosticMappingInfo((diag::kind)DiagID, State); if (MappingInfo == 0) { MappingInfo = GetDefaultDiagMapping(DiagID); Diag.setDiagnosticMappingInternal(DiagID, MappingInfo, State, false, false); } if (mapping) *mapping = (diag::Mapping) (MappingInfo & 7); bool ShouldEmitInSystemHeader = false; switch (MappingInfo & 7) { default: assert(0 && "Unknown mapping!"); case diag::MAP_IGNORE: // Ignore this, unless this is an extension diagnostic and we're mapping // them onto warnings or errors. if (!isBuiltinExtensionDiag(DiagID) || // Not an extension Diag.ExtBehavior == Diagnostic::Ext_Ignore || // Ext ignored (MappingInfo & 8) != 0) // User explicitly mapped it. return DiagnosticIDs::Ignored; Result = DiagnosticIDs::Warning; if (Diag.ExtBehavior == Diagnostic::Ext_Error) Result = DiagnosticIDs::Error; if (Result == DiagnosticIDs::Error && Diag.ErrorsAsFatal) Result = DiagnosticIDs::Fatal; break; case diag::MAP_ERROR: Result = DiagnosticIDs::Error; if (Diag.ErrorsAsFatal) Result = DiagnosticIDs::Fatal; break; case diag::MAP_FATAL: Result = DiagnosticIDs::Fatal; break; case diag::MAP_WARNING_SHOW_IN_SYSTEM_HEADER: ShouldEmitInSystemHeader = true; // continue as MAP_WARNING. case diag::MAP_WARNING: // If warnings are globally mapped to ignore or error, do it. if (Diag.IgnoreAllWarnings) return DiagnosticIDs::Ignored; Result = DiagnosticIDs::Warning; // If this is an extension diagnostic and we're in -pedantic-error mode, and // if the user didn't explicitly map it, upgrade to an error. if (Diag.ExtBehavior == Diagnostic::Ext_Error && (MappingInfo & 8) == 0 && isBuiltinExtensionDiag(DiagID)) Result = DiagnosticIDs::Error; if (Diag.WarningsAsErrors) Result = DiagnosticIDs::Error; if (Result == DiagnosticIDs::Error && Diag.ErrorsAsFatal) Result = DiagnosticIDs::Fatal; break; case diag::MAP_WARNING_NO_WERROR: // Diagnostics specified with -Wno-error=foo should be set to warnings, but // not be adjusted by -Werror or -pedantic-errors. Result = DiagnosticIDs::Warning; // If warnings are globally mapped to ignore or error, do it. if (Diag.IgnoreAllWarnings) return DiagnosticIDs::Ignored; break; case diag::MAP_ERROR_NO_WFATAL: // Diagnostics specified as -Wno-fatal-error=foo should be errors, but // unaffected by -Wfatal-errors. Result = DiagnosticIDs::Error; break; } // Okay, we're about to return this as a "diagnostic to emit" one last check: // if this is any sort of extension warning, and if we're in an __extension__ // block, silence it. if (Diag.AllExtensionsSilenced && isBuiltinExtensionDiag(DiagID)) return DiagnosticIDs::Ignored; // If we are in a system header, we ignore it. // We also want to ignore extensions and warnings in -Werror and // -pedantic-errors modes, which *map* warnings/extensions to errors. if (Result >= DiagnosticIDs::Warning && DiagClass != CLASS_ERROR && // Custom diagnostics always are emitted in system headers. DiagID < diag::DIAG_UPPER_LIMIT && !ShouldEmitInSystemHeader && Diag.SuppressSystemWarnings && Loc.isValid() && Diag.getSourceManager().isInSystemHeader( Diag.getSourceManager().getInstantiationLoc(Loc))) return DiagnosticIDs::Ignored; return Result; }
void UnreachableCodeChecker::checkEndAnalysis(ExplodedGraph &G, BugReporter &B, ExprEngine &Eng) const { CFGBlocksSet reachable, visited; if (Eng.hasWorkRemaining()) return; CFG *C = 0; ParentMap *PM = 0; const LocationContext *LC = 0; // Iterate over ExplodedGraph for (ExplodedGraph::node_iterator I = G.nodes_begin(), E = G.nodes_end(); I != E; ++I) { const ProgramPoint &P = I->getLocation(); LC = P.getLocationContext(); // Save the CFG if we don't have it already if (!C) C = LC->getAnalysisContext()->getUnoptimizedCFG(); if (!PM) PM = &LC->getParentMap(); if (const BlockEntrance *BE = dyn_cast<BlockEntrance>(&P)) { const CFGBlock *CB = BE->getBlock(); reachable.insert(CB->getBlockID()); } } // Bail out if we didn't get the CFG or the ParentMap. if (!C || !PM) return; ASTContext &Ctx = B.getContext(); // Find CFGBlocks that were not covered by any node for (CFG::const_iterator I = C->begin(), E = C->end(); I != E; ++I) { const CFGBlock *CB = *I; // Check if the block is unreachable if (reachable.count(CB->getBlockID())) continue; // Check if the block is empty (an artificial block) if (isEmptyCFGBlock(CB)) continue; // Find the entry points for this block if (!visited.count(CB->getBlockID())) FindUnreachableEntryPoints(CB, reachable, visited); // This block may have been pruned; check if we still want to report it if (reachable.count(CB->getBlockID())) continue; // Check for false positives if (CB->size() > 0 && isInvalidPath(CB, *PM)) continue; // Special case for __builtin_unreachable. // FIXME: This should be extended to include other unreachable markers, // such as llvm_unreachable. if (!CB->empty()) { bool foundUnreachable = false; for (CFGBlock::const_iterator ci = CB->begin(), ce = CB->end(); ci != ce; ++ci) { if (const CFGStmt *S = (*ci).getAs<CFGStmt>()) if (const CallExpr *CE = dyn_cast<CallExpr>(S->getStmt())) { if (CE->isBuiltinCall(Ctx) == Builtin::BI__builtin_unreachable) { foundUnreachable = true; break; } } } if (foundUnreachable) continue; } // We found a block that wasn't covered - find the statement to report SourceRange SR; PathDiagnosticLocation DL; SourceLocation SL; if (const Stmt *S = getUnreachableStmt(CB)) { SR = S->getSourceRange(); DL = PathDiagnosticLocation::createBegin(S, B.getSourceManager(), LC); SL = DL.asLocation(); if (SR.isInvalid() || !SL.isValid()) continue; } else continue; // Check if the SourceLocation is in a system header const SourceManager &SM = B.getSourceManager(); if (SM.isInSystemHeader(SL) || SM.isInExternCSystemHeader(SL)) continue; B.EmitBasicReport("Unreachable code", "Dead code", "This statement is never" " executed", DL, SR); } }
// FIXME: duplicate code in the QmlJS::Rewriter class, remove this void AddPropertyVisitor::addInMembers(QmlJS::AST::UiObjectInitializer *initializer) { UiObjectMemberList *insertAfter = searchMemberToInsertAfter(initializer->members, m_name, m_propertyOrder); SourceLocation endOfPreviousMember; SourceLocation startOfNextMember; unsigned depth; if (insertAfter == 0 || insertAfter->member == 0) { // insert as first member endOfPreviousMember = initializer->lbraceToken; if (initializer->members && initializer->members->member) startOfNextMember = initializer->members->member->firstSourceLocation(); else startOfNextMember = initializer->rbraceToken; depth = calculateIndentDepth(endOfPreviousMember) + indentDepth(); } else { endOfPreviousMember = insertAfter->member->lastSourceLocation(); if (insertAfter->next && insertAfter->next->member) startOfNextMember = insertAfter->next->member->firstSourceLocation(); else startOfNextMember = initializer->rbraceToken; depth = calculateIndentDepth(endOfPreviousMember); } const bool isOneLiner = endOfPreviousMember.startLine == startOfNextMember.startLine; bool needsPreceedingSemicolon = false; bool needsTrailingSemicolon = false; if (isOneLiner) { if (insertAfter == 0) { // we're inserting after an lbrace if (initializer->members) { // we're inserting before a member (and not the rbrace) needsTrailingSemicolon = m_propertyType == QmlRefactoring::ScriptBinding; } } else { // we're inserting after a member, not after the lbrace if (endOfPreviousMember.isValid()) { // there already is a semicolon after the previous member if (insertAfter->next && insertAfter->next->member) { // and the after us there is a member, not an rbrace, so: needsTrailingSemicolon = m_propertyType == QmlRefactoring::ScriptBinding; } } else { // there is no semicolon after the previous member (probably because there is an rbrace after us/it, so: needsPreceedingSemicolon = true; } } } QString newPropertyTemplate; switch (m_propertyType) { case QmlRefactoring::ArrayBinding: newPropertyTemplate = QLatin1String("%1: [\n%2\n]"); m_value = addIndentation(m_value, 4); break; case QmlRefactoring::ObjectBinding: newPropertyTemplate = QLatin1String("%1: %2"); break; case QmlRefactoring::ScriptBinding: newPropertyTemplate = QLatin1String("%1: %2"); break; default: Q_ASSERT(!"unknown property type"); } if (isOneLiner) { if (needsPreceedingSemicolon) newPropertyTemplate.prepend(QLatin1Char(';')); newPropertyTemplate.prepend(QLatin1Char(' ')); if (needsTrailingSemicolon) newPropertyTemplate.append(QLatin1Char(';')); depth = 0; } else { newPropertyTemplate.prepend(QLatin1Char('\n')); } const QString newPropertyText = addIndentation(newPropertyTemplate.arg(m_name, m_value), depth); replace(endOfPreviousMember.end(), 0, newPropertyText); setDidRewriting(true); }
Rewriter::Range Rewriter::addBinding(AST::UiObjectInitializer *ast, const QString &propertyName, const QString &propertyValue, BindingType bindingType, UiObjectMemberList *insertAfter) { SourceLocation endOfPreviousMember; SourceLocation startOfNextMember; if (insertAfter == 0 || insertAfter->member == 0) { // insert as first member endOfPreviousMember = ast->lbraceToken; if (ast->members && ast->members->member) startOfNextMember = ast->members->member->firstSourceLocation(); else startOfNextMember = ast->rbraceToken; } else { endOfPreviousMember = insertAfter->member->lastSourceLocation(); if (insertAfter->next && insertAfter->next->member) startOfNextMember = insertAfter->next->member->firstSourceLocation(); else startOfNextMember = ast->rbraceToken; } const bool isOneLiner = endOfPreviousMember.startLine == startOfNextMember.startLine; bool needsPreceedingSemicolon = false; bool needsTrailingSemicolon = false; if (isOneLiner) { if (insertAfter == 0) { // we're inserting after an lbrace if (ast->members) { // we're inserting before a member (and not the rbrace) needsTrailingSemicolon = bindingType == ScriptBinding; } } else { // we're inserting after a member, not after the lbrace if (endOfPreviousMember.isValid()) { // there already is a semicolon after the previous member if (insertAfter->next && insertAfter->next->member) { // and the after us there is a member, not an rbrace, so: needsTrailingSemicolon = bindingType == ScriptBinding; } } else { // there is no semicolon after the previous member (probably because there is an rbrace after us/it, so: needsPreceedingSemicolon = true; } } } QString newPropertyTemplate; switch (bindingType) { case ArrayBinding: newPropertyTemplate = QLatin1String("%1: [\n%2\n]"); break; case ObjectBinding: newPropertyTemplate = QLatin1String("%1: %2"); break; case ScriptBinding: newPropertyTemplate = QLatin1String("%1: %2"); break; default: Q_ASSERT(!"unknown property type"); } if (isOneLiner) { if (needsPreceedingSemicolon) newPropertyTemplate.prepend(QLatin1Char(';')); newPropertyTemplate.prepend(QLatin1Char(' ')); if (needsTrailingSemicolon) newPropertyTemplate.append(QLatin1Char(';')); } else { newPropertyTemplate.prepend(QLatin1Char('\n')); } m_changeSet->insert(endOfPreviousMember.end(), newPropertyTemplate.arg(propertyName, propertyValue)); return Range(endOfPreviousMember.end(), endOfPreviousMember.end()); }
void UnreachableCodeChecker::checkEndAnalysis(ExplodedGraph &G, BugReporter &B, ExprEngine &Eng) const { CFGBlocksSet reachable, visited; if (Eng.hasWorkRemaining()) return; const Decl *D = 0; CFG *C = 0; ParentMap *PM = 0; const LocationContext *LC = 0; // Iterate over ExplodedGraph for (ExplodedGraph::node_iterator I = G.nodes_begin(), E = G.nodes_end(); I != E; ++I) { const ProgramPoint &P = I->getLocation(); LC = P.getLocationContext(); if (!LC->inTopFrame()) continue; if (!D) D = LC->getAnalysisDeclContext()->getDecl(); // Save the CFG if we don't have it already if (!C) C = LC->getAnalysisDeclContext()->getUnoptimizedCFG(); if (!PM) PM = &LC->getParentMap(); if (Optional<BlockEntrance> BE = P.getAs<BlockEntrance>()) { const CFGBlock *CB = BE->getBlock(); reachable.insert(CB->getBlockID()); } } // Bail out if we didn't get the CFG or the ParentMap. if (!D || !C || !PM) return; // Don't do anything for template instantiations. Proving that code // in a template instantiation is unreachable means proving that it is // unreachable in all instantiations. if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) if (FD->isTemplateInstantiation()) return; // Find CFGBlocks that were not covered by any node for (CFG::const_iterator I = C->begin(), E = C->end(); I != E; ++I) { const CFGBlock *CB = *I; // Check if the block is unreachable if (reachable.count(CB->getBlockID())) continue; // Check if the block is empty (an artificial block) if (isEmptyCFGBlock(CB)) continue; // Find the entry points for this block if (!visited.count(CB->getBlockID())) FindUnreachableEntryPoints(CB, reachable, visited); // This block may have been pruned; check if we still want to report it if (reachable.count(CB->getBlockID())) continue; // Check for false positives if (CB->size() > 0 && isInvalidPath(CB, *PM)) continue; // It is good practice to always have a "default" label in a "switch", even // if we should never get there. It can be used to detect errors, for // instance. Unreachable code directly under a "default" label is therefore // likely to be a false positive. if (const Stmt *label = CB->getLabel()) if (label->getStmtClass() == Stmt::DefaultStmtClass) continue; // Special case for __builtin_unreachable. // FIXME: This should be extended to include other unreachable markers, // such as llvm_unreachable. if (!CB->empty()) { bool foundUnreachable = false; for (CFGBlock::const_iterator ci = CB->begin(), ce = CB->end(); ci != ce; ++ci) { if (Optional<CFGStmt> S = (*ci).getAs<CFGStmt>()) if (const CallExpr *CE = dyn_cast<CallExpr>(S->getStmt())) { if (CE->getBuiltinCallee() == Builtin::BI__builtin_unreachable) { foundUnreachable = true; break; } } } if (foundUnreachable) continue; } // We found a block that wasn't covered - find the statement to report SourceRange SR; PathDiagnosticLocation DL; SourceLocation SL; if (const Stmt *S = getUnreachableStmt(CB)) { SR = S->getSourceRange(); DL = PathDiagnosticLocation::createBegin(S, B.getSourceManager(), LC); SL = DL.asLocation(); if (SR.isInvalid() || !SL.isValid()) continue; } else continue; // Check if the SourceLocation is in a system header const SourceManager &SM = B.getSourceManager(); if (SM.isInSystemHeader(SL) || SM.isInExternCSystemHeader(SL)) continue; B.EmitBasicReport(D, this, "Unreachable code", "Dead code", "This statement is never executed", DL, SR); } }
/// \brief Based on the way the client configured the Diagnostic /// object, classify the specified diagnostic ID into a Level, consumable by /// the DiagnosticClient. /// /// \param Loc The source location we are interested in finding out the /// diagnostic state. Can be null in order to query the latest state. DiagnosticIDs::Level DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass, SourceLocation Loc, const DiagnosticsEngine &Diag) const { // Specific non-error diagnostics may be mapped to various levels from ignored // to error. Errors can only be mapped to fatal. DiagnosticIDs::Level Result = DiagnosticIDs::Fatal; DiagnosticsEngine::DiagStatePointsTy::iterator Pos = Diag.GetDiagStatePointForLoc(Loc); DiagnosticsEngine::DiagState *State = Pos->State; // Get the mapping information, or compute it lazily. DiagnosticMappingInfo &MappingInfo = State->getOrAddMappingInfo( (diag::kind)DiagID); switch (MappingInfo.getMapping()) { default: llvm_unreachable("Unknown mapping!"); case diag::MAP_IGNORE: Result = DiagnosticIDs::Ignored; break; case diag::MAP_WARNING: Result = DiagnosticIDs::Warning; break; case diag::MAP_ERROR: Result = DiagnosticIDs::Error; break; case diag::MAP_FATAL: Result = DiagnosticIDs::Fatal; break; } // Upgrade ignored diagnostics if -Weverything is enabled. if (Diag.EnableAllWarnings && Result == DiagnosticIDs::Ignored && !MappingInfo.isUser()) Result = DiagnosticIDs::Warning; // Ignore -pedantic diagnostics inside __extension__ blocks. // (The diagnostics controlled by -pedantic are the extension diagnostics // that are not enabled by default.) bool EnabledByDefault = false; bool IsExtensionDiag = isBuiltinExtensionDiag(DiagID, EnabledByDefault); if (Diag.AllExtensionsSilenced && IsExtensionDiag && !EnabledByDefault) return DiagnosticIDs::Ignored; // For extension diagnostics that haven't been explicitly mapped, check if we // should upgrade the diagnostic. if (IsExtensionDiag && !MappingInfo.isUser()) { switch (Diag.ExtBehavior) { case DiagnosticsEngine::Ext_Ignore: break; case DiagnosticsEngine::Ext_Warn: // Upgrade ignored diagnostics to warnings. if (Result == DiagnosticIDs::Ignored) Result = DiagnosticIDs::Warning; break; case DiagnosticsEngine::Ext_Error: // Upgrade ignored or warning diagnostics to errors. if (Result == DiagnosticIDs::Ignored || Result == DiagnosticIDs::Warning) Result = DiagnosticIDs::Error; break; } } // At this point, ignored errors can no longer be upgraded. if (Result == DiagnosticIDs::Ignored) return Result; // Honor -w, which is lower in priority than pedantic-errors, but higher than // -Werror. if (Result == DiagnosticIDs::Warning && Diag.IgnoreAllWarnings) return DiagnosticIDs::Ignored; // If -Werror is enabled, map warnings to errors unless explicitly disabled. if (Result == DiagnosticIDs::Warning) { if (Diag.WarningsAsErrors && !MappingInfo.hasNoWarningAsError()) Result = DiagnosticIDs::Error; } // If -Wfatal-errors is enabled, map errors to fatal unless explicity // disabled. if (Result == DiagnosticIDs::Error) { if (Diag.ErrorsAsFatal && !MappingInfo.hasNoErrorAsFatal()) Result = DiagnosticIDs::Fatal; } // If we are in a system header, we ignore it. We look at the diagnostic class // because we also want to ignore extensions and warnings in -Werror and // -pedantic-errors modes, which *map* warnings/extensions to errors. if (Result >= DiagnosticIDs::Warning && DiagClass != CLASS_ERROR && // Custom diagnostics always are emitted in system headers. DiagID < diag::DIAG_UPPER_LIMIT && !MappingInfo.hasShowInSystemHeader() && Diag.SuppressSystemWarnings && Loc.isValid() && Diag.getSourceManager().isInSystemHeader( Diag.getSourceManager().getExpansionLoc(Loc))) return DiagnosticIDs::Ignored; return Result; }
/// \brief Replace the tokens that form a simple-template-id with an /// annotation token containing the complete template-id. /// /// The first token in the stream must be the name of a template that /// is followed by a '<'. This routine will parse the complete /// simple-template-id and replace the tokens with a single annotation /// token with one of two different kinds: if the template-id names a /// type (and \p AllowTypeAnnotation is true), the annotation token is /// a type annotation that includes the optional nested-name-specifier /// (\p SS). Otherwise, the annotation token is a template-id /// annotation that does not include the optional /// nested-name-specifier. /// /// \param Template the declaration of the template named by the first /// token (an identifier), as returned from \c Action::isTemplateName(). /// /// \param TemplateNameKind the kind of template that \p Template /// refers to, as returned from \c Action::isTemplateName(). /// /// \param SS if non-NULL, the nested-name-specifier that precedes /// this template name. /// /// \param TemplateKWLoc if valid, specifies that this template-id /// annotation was preceded by the 'template' keyword and gives the /// location of that keyword. If invalid (the default), then this /// template-id was not preceded by a 'template' keyword. /// /// \param AllowTypeAnnotation if true (the default), then a /// simple-template-id that refers to a class template, template /// template parameter, or other template that produces a type will be /// replaced with a type annotation token. Otherwise, the /// simple-template-id is always replaced with a template-id /// annotation token. /// /// If an unrecoverable parse error occurs and no annotation token can be /// formed, this function returns true. /// bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, UnqualifiedId &TemplateName, bool AllowTypeAnnotation) { assert(getLangOpts().CPlusPlus && "Can only annotate template-ids in C++"); assert(Template && Tok.is(tok::less) && "Parser isn't at the beginning of a template-id"); // Consume the template-name. SourceLocation TemplateNameLoc = TemplateName.getSourceRange().getBegin(); // Parse the enclosed template argument list. SourceLocation LAngleLoc, RAngleLoc; TemplateArgList TemplateArgs; bool Invalid = ParseTemplateIdAfterTemplateName(Template, TemplateNameLoc, SS, false, LAngleLoc, TemplateArgs, RAngleLoc); if (Invalid) { // If we failed to parse the template ID but skipped ahead to a >, we're not // going to be able to form a token annotation. Eat the '>' if present. if (Tok.is(tok::greater)) ConsumeToken(); return true; } ASTTemplateArgsPtr TemplateArgsPtr(Actions, TemplateArgs.data(), TemplateArgs.size()); // Build the annotation token. if (TNK == TNK_Type_template && AllowTypeAnnotation) { TypeResult Type = Actions.ActOnTemplateIdType(SS, TemplateKWLoc, Template, TemplateNameLoc, LAngleLoc, TemplateArgsPtr, RAngleLoc); if (Type.isInvalid()) { // If we failed to parse the template ID but skipped ahead to a >, we're not // going to be able to form a token annotation. Eat the '>' if present. if (Tok.is(tok::greater)) ConsumeToken(); return true; } Tok.setKind(tok::annot_typename); setTypeAnnotation(Tok, Type.get()); if (SS.isNotEmpty()) Tok.setLocation(SS.getBeginLoc()); else if (TemplateKWLoc.isValid()) Tok.setLocation(TemplateKWLoc); else Tok.setLocation(TemplateNameLoc); } else { // Build a template-id annotation token that can be processed // later. Tok.setKind(tok::annot_template_id); TemplateIdAnnotation *TemplateId = TemplateIdAnnotation::Allocate(TemplateArgs.size()); TemplateId->TemplateNameLoc = TemplateNameLoc; if (TemplateName.getKind() == UnqualifiedId::IK_Identifier) { TemplateId->Name = TemplateName.Identifier; TemplateId->Operator = OO_None; } else { TemplateId->Name = 0; TemplateId->Operator = TemplateName.OperatorFunctionId.Operator; } TemplateId->SS = SS; TemplateId->TemplateKWLoc = TemplateKWLoc; TemplateId->Template = Template; TemplateId->Kind = TNK; TemplateId->LAngleLoc = LAngleLoc; TemplateId->RAngleLoc = RAngleLoc; ParsedTemplateArgument *Args = TemplateId->getTemplateArgs(); for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); Arg != ArgEnd; ++Arg) Args[Arg] = ParsedTemplateArgument(TemplateArgs[Arg]); Tok.setAnnotationValue(TemplateId); if (TemplateKWLoc.isValid()) Tok.setLocation(TemplateKWLoc); else Tok.setLocation(TemplateNameLoc); TemplateArgsPtr.release(); } // Common fields for the annotation token Tok.setAnnotationEndLoc(RAngleLoc); // In case the tokens were cached, have Preprocessor replace them with the // annotation token. PP.AnnotateCachedTokens(Tok); return false; }
/// \brief Emit a code snippet and caret line. /// /// This routine emits a single line's code snippet and caret line.. /// /// \param Loc The location for the caret. /// \param Ranges The underlined ranges for this code snippet. /// \param Hints The FixIt hints active for this diagnostic. void TextDiagnostic::emitSnippetAndCaret( SourceLocation Loc, DiagnosticsEngine::Level Level, SmallVectorImpl<CharSourceRange>& Ranges, ArrayRef<FixItHint> Hints, const SourceManager &SM) { assert(Loc.isValid() && "must have a valid source location here"); assert(Loc.isFileID() && "must have a file location here"); // If caret diagnostics are enabled and we have location, we want to // emit the caret. However, we only do this if the location moved // from the last diagnostic, if the last diagnostic was a note that // was part of a different warning or error diagnostic, or if the // diagnostic has ranges. We don't want to emit the same caret // multiple times if one loc has multiple diagnostics. if (!DiagOpts->ShowCarets) return; if (Loc == LastLoc && Ranges.empty() && Hints.empty() && (LastLevel != DiagnosticsEngine::Note || Level == LastLevel)) return; // Decompose the location into a FID/Offset pair. std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc); FileID FID = LocInfo.first; unsigned FileOffset = LocInfo.second; // Get information about the buffer it points into. bool Invalid = false; StringRef BufData = SM.getBufferData(FID, &Invalid); if (Invalid) return; const char *BufStart = BufData.data(); const char *BufEnd = BufStart + BufData.size(); unsigned LineNo = SM.getLineNumber(FID, FileOffset); unsigned ColNo = SM.getColumnNumber(FID, FileOffset); // Arbitrarily stop showing snippets when the line is too long. static const size_t MaxLineLengthToPrint = 4096; if (ColNo > MaxLineLengthToPrint) return; // Rewind from the current position to the start of the line. const char *TokPtr = BufStart+FileOffset; const char *LineStart = TokPtr-ColNo+1; // Column # is 1-based. // Compute the line end. Scan forward from the error position to the end of // the line. const char *LineEnd = TokPtr; while (*LineEnd != '\n' && *LineEnd != '\r' && LineEnd != BufEnd) ++LineEnd; // Arbitrarily stop showing snippets when the line is too long. if (size_t(LineEnd - LineStart) > MaxLineLengthToPrint) return; // Trim trailing null-bytes. StringRef Line(LineStart, LineEnd - LineStart); while (Line.size() > ColNo && Line.back() == '\0') Line = Line.drop_back(); // Copy the line of code into an std::string for ease of manipulation. std::string SourceLine(Line.begin(), Line.end()); // Build the byte to column map. const SourceColumnMap sourceColMap(SourceLine, DiagOpts->TabStop); // Create a line for the caret that is filled with spaces that is the same // number of columns as the line of source code. std::string CaretLine(sourceColMap.columns(), ' '); // Highlight all of the characters covered by Ranges with ~ characters. for (SmallVectorImpl<CharSourceRange>::iterator I = Ranges.begin(), E = Ranges.end(); I != E; ++I) highlightRange(*I, LineNo, FID, sourceColMap, CaretLine, SM, LangOpts); // Next, insert the caret itself. ColNo = sourceColMap.byteToContainingColumn(ColNo-1); if (CaretLine.size()<ColNo+1) CaretLine.resize(ColNo+1, ' '); CaretLine[ColNo] = '^'; std::string FixItInsertionLine = buildFixItInsertionLine(LineNo, sourceColMap, Hints, SM, DiagOpts.get()); // If the source line is too long for our terminal, select only the // "interesting" source region within that line. unsigned Columns = DiagOpts->MessageLength; if (Columns) selectInterestingSourceRegion(SourceLine, CaretLine, FixItInsertionLine, Columns, sourceColMap); // If we are in -fdiagnostics-print-source-range-info mode, we are trying // to produce easily machine parsable output. Add a space before the // source line and the caret to make it trivial to tell the main diagnostic // line from what the user is intended to see. if (DiagOpts->ShowSourceRanges) { SourceLine = ' ' + SourceLine; CaretLine = ' ' + CaretLine; } // Finally, remove any blank spaces from the end of CaretLine. while (CaretLine[CaretLine.size()-1] == ' ') CaretLine.erase(CaretLine.end()-1); // Emit what we have computed. emitSnippet(SourceLine); if (DiagOpts->ShowColors) OS.changeColor(caretColor, true); OS << CaretLine << '\n'; if (DiagOpts->ShowColors) OS.resetColor(); if (!FixItInsertionLine.empty()) { if (DiagOpts->ShowColors) // Print fixit line in color OS.changeColor(fixitColor, false); if (DiagOpts->ShowSourceRanges) OS << ' '; OS << FixItInsertionLine << '\n'; if (DiagOpts->ShowColors) OS.resetColor(); } // Print out any parseable fixit information requested by the options. emitParseableFixits(Hints, SM); }
/// \param ReceiverType The type of the object receiving the /// message. When \p ReceiverTypeInfo is non-NULL, this is the same /// type as that refers to. For a superclass send, this is the type of /// the superclass. /// /// \param SuperLoc The location of the "super" keyword in a /// superclass message. /// /// \param Sel The selector to which the message is being sent. /// /// \param Method The method that this class message is invoking, if /// already known. /// /// \param LBracLoc The location of the opening square bracket ']'. /// /// \param RBrac The location of the closing square bracket ']'. /// /// \param Args The message arguments. Sema::OwningExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, QualType ReceiverType, SourceLocation SuperLoc, Selector Sel, ObjCMethodDecl *Method, SourceLocation LBracLoc, SourceLocation RBracLoc, MultiExprArg ArgsIn) { if (ReceiverType->isDependentType()) { // If the receiver type is dependent, we can't type-check anything // at this point. Build a dependent expression. unsigned NumArgs = ArgsIn.size(); Expr **Args = reinterpret_cast<Expr **>(ArgsIn.release()); assert(SuperLoc.isInvalid() && "Message to super with dependent type"); return Owned(ObjCMessageExpr::Create(Context, ReceiverType, LBracLoc, ReceiverTypeInfo, Sel, /*Method=*/0, Args, NumArgs, RBracLoc)); } SourceLocation Loc = SuperLoc.isValid()? SuperLoc : ReceiverTypeInfo->getTypeLoc().getLocalSourceRange().getBegin(); // Find the class to which we are sending this message. ObjCInterfaceDecl *Class = 0; const ObjCObjectType *ClassType = ReceiverType->getAs<ObjCObjectType>(); if (!ClassType || !(Class = ClassType->getInterface())) { Diag(Loc, diag::err_invalid_receiver_class_message) << ReceiverType; return ExprError(); } assert(Class && "We don't know which class we're messaging?"); // Find the method we are messaging. if (!Method) { if (Class->isForwardDecl()) { // A forward class used in messaging is treated as a 'Class' Diag(Loc, diag::warn_receiver_forward_class) << Class->getDeclName(); Method = LookupFactoryMethodInGlobalPool(Sel, SourceRange(LBracLoc, RBracLoc)); if (Method) Diag(Method->getLocation(), diag::note_method_sent_forward_class) << Method->getDeclName(); } if (!Method) Method = Class->lookupClassMethod(Sel); // If we have an implementation in scope, check "private" methods. if (!Method) Method = LookupPrivateClassMethod(Sel, Class); if (Method && DiagnoseUseOfDecl(Method, Loc)) return ExprError(); } // Check the argument types and determine the result type. QualType ReturnType; unsigned NumArgs = ArgsIn.size(); Expr **Args = reinterpret_cast<Expr **>(ArgsIn.release()); if (CheckMessageArgumentTypes(Args, NumArgs, Sel, Method, true, LBracLoc, RBracLoc, ReturnType)) return ExprError(); // Construct the appropriate ObjCMessageExpr. Expr *Result; if (SuperLoc.isValid()) Result = ObjCMessageExpr::Create(Context, ReturnType, LBracLoc, SuperLoc, /*IsInstanceSuper=*/false, ReceiverType, Sel, Method, Args, NumArgs, RBracLoc); else Result = ObjCMessageExpr::Create(Context, ReturnType, LBracLoc, ReceiverTypeInfo, Sel, Method, Args, NumArgs, RBracLoc); return MaybeBindToTemporary(Result); }