Sema.cpp revision 8c465e6494d16a19127873dc9bdc55177ac6b6fd
1//===--- Sema.cpp - AST Builder and Semantic Analysis Implementation ------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file implements the actions class which performs semantic analysis and 11// builds an AST out of a parse stream. 12// 13//===----------------------------------------------------------------------===// 14 15#include "clang/Sema/SemaInternal.h" 16#include "clang/Sema/DelayedDiagnostic.h" 17#include "TargetAttributesSema.h" 18#include "llvm/ADT/DenseMap.h" 19#include "llvm/ADT/SmallSet.h" 20#include "llvm/ADT/APFloat.h" 21#include "clang/Sema/CXXFieldCollector.h" 22#include "clang/Sema/ExternalSemaSource.h" 23#include "clang/Sema/PrettyDeclStackTrace.h" 24#include "clang/Sema/Scope.h" 25#include "clang/Sema/ScopeInfo.h" 26#include "clang/Sema/SemaConsumer.h" 27#include "clang/AST/ASTContext.h" 28#include "clang/AST/ASTDiagnostic.h" 29#include "clang/AST/DeclCXX.h" 30#include "clang/AST/DeclObjC.h" 31#include "clang/AST/Expr.h" 32#include "clang/Lex/Preprocessor.h" 33#include "clang/Basic/PartialDiagnostic.h" 34#include "clang/Basic/TargetInfo.h" 35using namespace clang; 36using namespace sema; 37 38FunctionScopeInfo::~FunctionScopeInfo() { } 39 40void FunctionScopeInfo::Clear(unsigned NumErrors) { 41 HasBranchProtectedScope = false; 42 HasBranchIntoScope = false; 43 HasIndirectGoto = false; 44 45 LabelMap.clear(); 46 SwitchStack.clear(); 47 Returns.clear(); 48 NumErrorsAtStartOfFunction = NumErrors; 49} 50 51BlockScopeInfo::~BlockScopeInfo() { } 52 53void Sema::ActOnTranslationUnitScope(Scope *S) { 54 TUScope = S; 55 PushDeclContext(S, Context.getTranslationUnitDecl()); 56 57 VAListTagName = PP.getIdentifierInfo("__va_list_tag"); 58 59 if (!Context.isInt128Installed() && // May be set by ASTReader. 60 PP.getTargetInfo().getPointerWidth(0) >= 64) { 61 TypeSourceInfo *TInfo; 62 63 // Install [u]int128_t for 64-bit targets. 64 TInfo = Context.getTrivialTypeSourceInfo(Context.Int128Ty); 65 PushOnScopeChains(TypedefDecl::Create(Context, CurContext, 66 SourceLocation(), 67 &Context.Idents.get("__int128_t"), 68 TInfo), TUScope); 69 70 TInfo = Context.getTrivialTypeSourceInfo(Context.UnsignedInt128Ty); 71 PushOnScopeChains(TypedefDecl::Create(Context, CurContext, 72 SourceLocation(), 73 &Context.Idents.get("__uint128_t"), 74 TInfo), TUScope); 75 Context.setInt128Installed(); 76 } 77 78 79 if (!PP.getLangOptions().ObjC1) return; 80 81 // Built-in ObjC types may already be set by ASTReader (hence isNull checks). 82 if (Context.getObjCSelType().isNull()) { 83 // Create the built-in typedef for 'SEL'. 84 QualType SelT = Context.getPointerType(Context.ObjCBuiltinSelTy); 85 TypeSourceInfo *SelInfo = Context.getTrivialTypeSourceInfo(SelT); 86 TypedefDecl *SelTypedef 87 = TypedefDecl::Create(Context, CurContext, SourceLocation(), 88 &Context.Idents.get("SEL"), SelInfo); 89 PushOnScopeChains(SelTypedef, TUScope); 90 Context.setObjCSelType(Context.getTypeDeclType(SelTypedef)); 91 Context.ObjCSelRedefinitionType = Context.getObjCSelType(); 92 } 93 94 // Synthesize "@class Protocol; 95 if (Context.getObjCProtoType().isNull()) { 96 ObjCInterfaceDecl *ProtocolDecl = 97 ObjCInterfaceDecl::Create(Context, CurContext, SourceLocation(), 98 &Context.Idents.get("Protocol"), 99 SourceLocation(), true); 100 Context.setObjCProtoType(Context.getObjCInterfaceType(ProtocolDecl)); 101 PushOnScopeChains(ProtocolDecl, TUScope, false); 102 } 103 // Create the built-in typedef for 'id'. 104 if (Context.getObjCIdType().isNull()) { 105 QualType T = Context.getObjCObjectType(Context.ObjCBuiltinIdTy, 0, 0); 106 T = Context.getObjCObjectPointerType(T); 107 TypeSourceInfo *IdInfo = Context.getTrivialTypeSourceInfo(T); 108 TypedefDecl *IdTypedef 109 = TypedefDecl::Create(Context, CurContext, SourceLocation(), 110 &Context.Idents.get("id"), IdInfo); 111 PushOnScopeChains(IdTypedef, TUScope); 112 Context.setObjCIdType(Context.getTypeDeclType(IdTypedef)); 113 Context.ObjCIdRedefinitionType = Context.getObjCIdType(); 114 } 115 // Create the built-in typedef for 'Class'. 116 if (Context.getObjCClassType().isNull()) { 117 QualType T = Context.getObjCObjectType(Context.ObjCBuiltinClassTy, 0, 0); 118 T = Context.getObjCObjectPointerType(T); 119 TypeSourceInfo *ClassInfo = Context.getTrivialTypeSourceInfo(T); 120 TypedefDecl *ClassTypedef 121 = TypedefDecl::Create(Context, CurContext, SourceLocation(), 122 &Context.Idents.get("Class"), ClassInfo); 123 PushOnScopeChains(ClassTypedef, TUScope); 124 Context.setObjCClassType(Context.getTypeDeclType(ClassTypedef)); 125 Context.ObjCClassRedefinitionType = Context.getObjCClassType(); 126 } 127} 128 129Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, 130 bool CompleteTranslationUnit, 131 CodeCompleteConsumer *CodeCompleter) 132 : TheTargetAttributesSema(0), 133 LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer), 134 Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()), 135 ExternalSource(0), CodeCompleter(CodeCompleter), CurContext(0), 136 PackContext(0), VisContext(0), ParsingDeclDepth(0), 137 IdResolver(pp.getLangOptions()), GlobalNewDeleteDeclared(false), 138 CompleteTranslationUnit(CompleteTranslationUnit), 139 NumSFINAEErrors(0), SuppressAccessChecking(false), 140 NonInstantiationEntries(0), CurrentInstantiationScope(0), TyposCorrected(0), 141 AnalysisWarnings(*this) 142{ 143 TUScope = 0; 144 if (getLangOptions().CPlusPlus) 145 FieldCollector.reset(new CXXFieldCollector()); 146 147 // Tell diagnostics how to render things from the AST library. 148 PP.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument, 149 &Context); 150 151 ExprEvalContexts.push_back( 152 ExpressionEvaluationContextRecord(PotentiallyEvaluated, 0)); 153 154 FunctionScopes.push_back(new FunctionScopeInfo(Diags.getNumErrors())); 155} 156 157void Sema::Initialize() { 158 // Tell the AST consumer about this Sema object. 159 Consumer.Initialize(Context); 160 161 // FIXME: Isn't this redundant with the initialization above? 162 if (SemaConsumer *SC = dyn_cast<SemaConsumer>(&Consumer)) 163 SC->InitializeSema(*this); 164 165 // Tell the external Sema source about this Sema object. 166 if (ExternalSemaSource *ExternalSema 167 = dyn_cast_or_null<ExternalSemaSource>(Context.getExternalSource())) 168 ExternalSema->InitializeSema(*this); 169} 170 171Sema::~Sema() { 172 if (PackContext) FreePackedContext(); 173 if (VisContext) FreeVisContext(); 174 delete TheTargetAttributesSema; 175 176 // Kill all the active scopes. 177 for (unsigned I = 1, E = FunctionScopes.size(); I != E; ++I) 178 delete FunctionScopes[I]; 179 if (FunctionScopes.size() == 1) 180 delete FunctionScopes[0]; 181 182 // Tell the SemaConsumer to forget about us; we're going out of scope. 183 if (SemaConsumer *SC = dyn_cast<SemaConsumer>(&Consumer)) 184 SC->ForgetSema(); 185 186 // Detach from the external Sema source. 187 if (ExternalSemaSource *ExternalSema 188 = dyn_cast_or_null<ExternalSemaSource>(Context.getExternalSource())) 189 ExternalSema->ForgetSema(); 190} 191 192/// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast. 193/// If there is already an implicit cast, merge into the existing one. 194/// The result is of the given category. 195void Sema::ImpCastExprToType(Expr *&Expr, QualType Ty, 196 CastKind Kind, ExprValueKind VK, 197 const CXXCastPath *BasePath) { 198 QualType ExprTy = Context.getCanonicalType(Expr->getType()); 199 QualType TypeTy = Context.getCanonicalType(Ty); 200 201 if (ExprTy == TypeTy) 202 return; 203 204 if (Expr->getType()->isPointerType() && Ty->isPointerType()) { 205 QualType ExprBaseType = cast<PointerType>(ExprTy)->getPointeeType(); 206 QualType BaseType = cast<PointerType>(TypeTy)->getPointeeType(); 207 if (ExprBaseType.getAddressSpace() != BaseType.getAddressSpace()) { 208 Diag(Expr->getExprLoc(), diag::err_implicit_pointer_address_space_cast) 209 << Expr->getSourceRange(); 210 } 211 } 212 213 // If this is a derived-to-base cast to a through a virtual base, we 214 // need a vtable. 215 if (Kind == CK_DerivedToBase && 216 BasePathInvolvesVirtualBase(*BasePath)) { 217 QualType T = Expr->getType(); 218 if (const PointerType *Pointer = T->getAs<PointerType>()) 219 T = Pointer->getPointeeType(); 220 if (const RecordType *RecordTy = T->getAs<RecordType>()) 221 MarkVTableUsed(Expr->getLocStart(), 222 cast<CXXRecordDecl>(RecordTy->getDecl())); 223 } 224 225 if (ImplicitCastExpr *ImpCast = dyn_cast<ImplicitCastExpr>(Expr)) { 226 if (ImpCast->getCastKind() == Kind && (!BasePath || BasePath->empty())) { 227 ImpCast->setType(Ty); 228 ImpCast->setValueKind(VK); 229 return; 230 } 231 } 232 233 Expr = ImplicitCastExpr::Create(Context, Ty, Kind, Expr, BasePath, VK); 234} 235 236ExprValueKind Sema::CastCategory(Expr *E) { 237 Expr::Classification Classification = E->Classify(Context); 238 return Classification.isRValue() ? VK_RValue : 239 (Classification.isLValue() ? VK_LValue : VK_XValue); 240} 241 242/// \brief Used to prune the decls of Sema's UnusedFileScopedDecls vector. 243static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) { 244 if (D->isUsed()) 245 return true; 246 247 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 248 // UnusedFileScopedDecls stores the first declaration. 249 // The declaration may have become definition so check again. 250 const FunctionDecl *DeclToCheck; 251 if (FD->hasBody(DeclToCheck)) 252 return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck); 253 254 // Later redecls may add new information resulting in not having to warn, 255 // so check again. 256 DeclToCheck = FD->getMostRecentDeclaration(); 257 if (DeclToCheck != FD) 258 return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck); 259 } 260 261 if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { 262 // UnusedFileScopedDecls stores the first declaration. 263 // The declaration may have become definition so check again. 264 const VarDecl *DeclToCheck = VD->getDefinition(); 265 if (DeclToCheck) 266 return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck); 267 268 // Later redecls may add new information resulting in not having to warn, 269 // so check again. 270 DeclToCheck = VD->getMostRecentDeclaration(); 271 if (DeclToCheck != VD) 272 return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck); 273 } 274 275 return false; 276} 277 278/// ActOnEndOfTranslationUnit - This is called at the very end of the 279/// translation unit when EOF is reached and all but the top-level scope is 280/// popped. 281void Sema::ActOnEndOfTranslationUnit() { 282 // At PCH writing, implicit instantiations and VTable handling info are 283 // stored and performed when the PCH is included. 284 if (CompleteTranslationUnit) 285 while (1) { 286 // C++: Perform implicit template instantiations. 287 // 288 // FIXME: When we perform these implicit instantiations, we do not 289 // carefully keep track of the point of instantiation (C++ [temp.point]). 290 // This means that name lookup that occurs within the template 291 // instantiation will always happen at the end of the translation unit, 292 // so it will find some names that should not be found. Although this is 293 // common behavior for C++ compilers, it is technically wrong. In the 294 // future, we either need to be able to filter the results of name lookup 295 // or we need to perform template instantiations earlier. 296 PerformPendingInstantiations(); 297 298 /// If DefinedUsedVTables ends up marking any virtual member 299 /// functions it might lead to more pending template 300 /// instantiations, which is why we need to loop here. 301 if (!DefineUsedVTables()) 302 break; 303 } 304 305 // Remove file scoped decls that turned out to be used. 306 UnusedFileScopedDecls.erase(std::remove_if(UnusedFileScopedDecls.begin(), 307 UnusedFileScopedDecls.end(), 308 std::bind1st(std::ptr_fun(ShouldRemoveFromUnused), 309 this)), 310 UnusedFileScopedDecls.end()); 311 312 if (!CompleteTranslationUnit) { 313 TUScope = 0; 314 return; 315 } 316 317 // Check for #pragma weak identifiers that were never declared 318 // FIXME: This will cause diagnostics to be emitted in a non-determinstic 319 // order! Iterating over a densemap like this is bad. 320 for (llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator 321 I = WeakUndeclaredIdentifiers.begin(), 322 E = WeakUndeclaredIdentifiers.end(); I != E; ++I) { 323 if (I->second.getUsed()) continue; 324 325 Diag(I->second.getLocation(), diag::warn_weak_identifier_undeclared) 326 << I->first; 327 } 328 329 // C99 6.9.2p2: 330 // A declaration of an identifier for an object that has file 331 // scope without an initializer, and without a storage-class 332 // specifier or with the storage-class specifier static, 333 // constitutes a tentative definition. If a translation unit 334 // contains one or more tentative definitions for an identifier, 335 // and the translation unit contains no external definition for 336 // that identifier, then the behavior is exactly as if the 337 // translation unit contains a file scope declaration of that 338 // identifier, with the composite type as of the end of the 339 // translation unit, with an initializer equal to 0. 340 llvm::SmallSet<VarDecl *, 32> Seen; 341 for (unsigned i = 0, e = TentativeDefinitions.size(); i != e; ++i) { 342 VarDecl *VD = TentativeDefinitions[i]->getActingDefinition(); 343 344 // If the tentative definition was completed, getActingDefinition() returns 345 // null. If we've already seen this variable before, insert()'s second 346 // return value is false. 347 if (VD == 0 || VD->isInvalidDecl() || !Seen.insert(VD)) 348 continue; 349 350 if (const IncompleteArrayType *ArrayT 351 = Context.getAsIncompleteArrayType(VD->getType())) { 352 if (RequireCompleteType(VD->getLocation(), 353 ArrayT->getElementType(), 354 diag::err_tentative_def_incomplete_type_arr)) { 355 VD->setInvalidDecl(); 356 continue; 357 } 358 359 // Set the length of the array to 1 (C99 6.9.2p5). 360 Diag(VD->getLocation(), diag::warn_tentative_incomplete_array); 361 llvm::APInt One(Context.getTypeSize(Context.getSizeType()), true); 362 QualType T = Context.getConstantArrayType(ArrayT->getElementType(), 363 One, ArrayType::Normal, 0); 364 VD->setType(T); 365 } else if (RequireCompleteType(VD->getLocation(), VD->getType(), 366 diag::err_tentative_def_incomplete_type)) 367 VD->setInvalidDecl(); 368 369 // Notify the consumer that we've completed a tentative definition. 370 if (!VD->isInvalidDecl()) 371 Consumer.CompleteTentativeDefinition(VD); 372 373 } 374 375 // Output warning for unused file scoped decls. 376 for (llvm::SmallVectorImpl<const DeclaratorDecl*>::iterator 377 I = UnusedFileScopedDecls.begin(), 378 E = UnusedFileScopedDecls.end(); I != E; ++I) { 379 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) { 380 const FunctionDecl *DiagD; 381 if (!FD->hasBody(DiagD)) 382 DiagD = FD; 383 Diag(DiagD->getLocation(), 384 isa<CXXMethodDecl>(DiagD) ? diag::warn_unused_member_function 385 : diag::warn_unused_function) 386 << DiagD->getDeclName(); 387 } else { 388 const VarDecl *DiagD = cast<VarDecl>(*I)->getDefinition(); 389 if (!DiagD) 390 DiagD = cast<VarDecl>(*I); 391 Diag(DiagD->getLocation(), diag::warn_unused_variable) 392 << DiagD->getDeclName(); 393 } 394 } 395 396 TUScope = 0; 397} 398 399 400//===----------------------------------------------------------------------===// 401// Helper functions. 402//===----------------------------------------------------------------------===// 403 404DeclContext *Sema::getFunctionLevelDeclContext() { 405 DeclContext *DC = CurContext; 406 407 while (isa<BlockDecl>(DC) || isa<EnumDecl>(DC)) 408 DC = DC->getParent(); 409 410 return DC; 411} 412 413/// getCurFunctionDecl - If inside of a function body, this returns a pointer 414/// to the function decl for the function being parsed. If we're currently 415/// in a 'block', this returns the containing context. 416FunctionDecl *Sema::getCurFunctionDecl() { 417 DeclContext *DC = getFunctionLevelDeclContext(); 418 return dyn_cast<FunctionDecl>(DC); 419} 420 421ObjCMethodDecl *Sema::getCurMethodDecl() { 422 DeclContext *DC = getFunctionLevelDeclContext(); 423 return dyn_cast<ObjCMethodDecl>(DC); 424} 425 426NamedDecl *Sema::getCurFunctionOrMethodDecl() { 427 DeclContext *DC = getFunctionLevelDeclContext(); 428 if (isa<ObjCMethodDecl>(DC) || isa<FunctionDecl>(DC)) 429 return cast<NamedDecl>(DC); 430 return 0; 431} 432 433Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() { 434 if (!this->Emit()) 435 return; 436 437 // If this is not a note, and we're in a template instantiation 438 // that is different from the last template instantiation where 439 // we emitted an error, print a template instantiation 440 // backtrace. 441 if (!SemaRef.Diags.isBuiltinNote(DiagID) && 442 !SemaRef.ActiveTemplateInstantiations.empty() && 443 SemaRef.ActiveTemplateInstantiations.back() 444 != SemaRef.LastTemplateInstantiationErrorContext) { 445 SemaRef.PrintInstantiationStack(); 446 SemaRef.LastTemplateInstantiationErrorContext 447 = SemaRef.ActiveTemplateInstantiations.back(); 448 } 449} 450 451Sema::SemaDiagnosticBuilder Sema::Diag(SourceLocation Loc, unsigned DiagID) { 452 if (isSFINAEContext()) { 453 switch (Diagnostic::getDiagnosticSFINAEResponse(DiagID)) { 454 case Diagnostic::SFINAE_Report: 455 // Fall through; we'll report the diagnostic below. 456 break; 457 458 case Diagnostic::SFINAE_SubstitutionFailure: 459 // Count this failure so that we know that template argument deduction 460 // has failed. 461 ++NumSFINAEErrors; 462 // Fall through 463 464 case Diagnostic::SFINAE_Suppress: 465 // Suppress this diagnostic. 466 Diags.setLastDiagnosticIgnored(); 467 return SemaDiagnosticBuilder(*this); 468 } 469 } 470 471 DiagnosticBuilder DB = Diags.Report(FullSourceLoc(Loc, SourceMgr), DiagID); 472 return SemaDiagnosticBuilder(DB, *this, DiagID); 473} 474 475Sema::SemaDiagnosticBuilder 476Sema::Diag(SourceLocation Loc, const PartialDiagnostic& PD) { 477 SemaDiagnosticBuilder Builder(Diag(Loc, PD.getDiagID())); 478 PD.Emit(Builder); 479 480 return Builder; 481} 482 483/// \brief Determines the active Scope associated with the given declaration 484/// context. 485/// 486/// This routine maps a declaration context to the active Scope object that 487/// represents that declaration context in the parser. It is typically used 488/// from "scope-less" code (e.g., template instantiation, lazy creation of 489/// declarations) that injects a name for name-lookup purposes and, therefore, 490/// must update the Scope. 491/// 492/// \returns The scope corresponding to the given declaraion context, or NULL 493/// if no such scope is open. 494Scope *Sema::getScopeForContext(DeclContext *Ctx) { 495 496 if (!Ctx) 497 return 0; 498 499 Ctx = Ctx->getPrimaryContext(); 500 for (Scope *S = getCurScope(); S; S = S->getParent()) { 501 // Ignore scopes that cannot have declarations. This is important for 502 // out-of-line definitions of static class members. 503 if (S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope)) 504 if (DeclContext *Entity = static_cast<DeclContext *> (S->getEntity())) 505 if (Ctx == Entity->getPrimaryContext()) 506 return S; 507 } 508 509 return 0; 510} 511 512/// \brief Enter a new function scope 513void Sema::PushFunctionScope() { 514 if (FunctionScopes.size() == 1) { 515 // Use the "top" function scope rather than having to allocate 516 // memory for a new scope. 517 FunctionScopes.back()->Clear(getDiagnostics().getNumErrors()); 518 FunctionScopes.push_back(FunctionScopes.back()); 519 return; 520 } 521 522 FunctionScopes.push_back( 523 new FunctionScopeInfo(getDiagnostics().getNumErrors())); 524} 525 526void Sema::PushBlockScope(Scope *BlockScope, BlockDecl *Block) { 527 FunctionScopes.push_back(new BlockScopeInfo(getDiagnostics().getNumErrors(), 528 BlockScope, Block)); 529} 530 531void Sema::PopFunctionOrBlockScope() { 532 FunctionScopeInfo *Scope = FunctionScopes.pop_back_val(); 533 assert(!FunctionScopes.empty() && "mismatched push/pop!"); 534 if (FunctionScopes.back() != Scope) 535 delete Scope; 536} 537 538/// \brief Determine whether any errors occurred within this function/method/ 539/// block. 540bool Sema::hasAnyErrorsInThisFunction() const { 541 return getCurFunction()->NumErrorsAtStartOfFunction 542 != getDiagnostics().getNumErrors(); 543} 544 545BlockScopeInfo *Sema::getCurBlock() { 546 if (FunctionScopes.empty()) 547 return 0; 548 549 return dyn_cast<BlockScopeInfo>(FunctionScopes.back()); 550} 551 552// Pin this vtable to this file. 553ExternalSemaSource::~ExternalSemaSource() {} 554 555void PrettyDeclStackTraceEntry::print(llvm::raw_ostream &OS) const { 556 SourceLocation Loc = this->Loc; 557 if (!Loc.isValid() && TheDecl) Loc = TheDecl->getLocation(); 558 if (Loc.isValid()) { 559 Loc.print(OS, S.getSourceManager()); 560 OS << ": "; 561 } 562 OS << Message; 563 564 if (TheDecl && isa<NamedDecl>(TheDecl)) { 565 std::string Name = cast<NamedDecl>(TheDecl)->getNameAsString(); 566 if (!Name.empty()) 567 OS << " '" << Name << '\''; 568 } 569 570 OS << '\n'; 571} 572