diff options
Diffstat (limited to 'lib/CodeGen')
| -rw-r--r-- | lib/CodeGen/CodeGen.cc | 4 | ||||
| -rw-r--r-- | lib/CodeGen/Designator.cc | 4 | ||||
| -rw-r--r-- | lib/CodeGen/TypeSystem.cc | 29 |
3 files changed, 24 insertions, 13 deletions
diff --git a/lib/CodeGen/CodeGen.cc b/lib/CodeGen/CodeGen.cc index d81c4ff..e45a3db 100644 --- a/lib/CodeGen/CodeGen.cc +++ b/lib/CodeGen/CodeGen.cc @@ -364,7 +364,9 @@ void CodeGen::compile(const std::vector<SourceUnit> &Sources) { RuntimeChecker->emitStderr(Msg); Builder->CreateRet(ConstantInt::get(Type::getInt32Ty(*TheContext), 1)); - if (verifyModule(*TheModule, &errs())) { + // After a reported error the IR may be incomplete; verifying it would only + // dump noise behind the real diagnostic. + if (!HadError && verifyModule(*TheModule, &errs())) { errs() << cps::diagnosticPrefix(cps::Severity::Fatal, "") << "LLVM module verification failed\n"; HadError = true; } diff --git a/lib/CodeGen/Designator.cc b/lib/CodeGen/Designator.cc index 4f0e82b..6737937 100644 --- a/lib/CodeGen/Designator.cc +++ b/lib/CodeGen/Designator.cc @@ -219,7 +219,9 @@ bool CodeGen::emitLValue(ExprAST *E, LValueInfo &Out) { } const RecordFieldInfo *FI = RP->findField(A.FieldName); if (!FI) { - reportError("Record type %s has no field %s", TypeName.c_str(), A.FieldName.c_str()); + // The rejected field was already reported with its record. + if (!RP->Invalid) + reportError("Record type %s has no field %s", TypeName.c_str(), A.FieldName.c_str()); return false; } if (!FI->IsPublic && !sameIdentifier(CurrentClass, TypeName)) { diff --git a/lib/CodeGen/TypeSystem.cc b/lib/CodeGen/TypeSystem.cc index ee177fb..a567562 100644 --- a/lib/CodeGen/TypeSystem.cc +++ b/lib/CodeGen/TypeSystem.cc @@ -199,32 +199,38 @@ bool TypeSystem::defineRecord(const std::string &Name, return false; } + // A bad field is skipped so the record still gets a body; Err keeps the + // first diagnostic and Invalid silences follow-up missing-field errors. std::vector<Type*> FieldTypes; RecordPayload Payload; + auto Bad = [&](std::string Message) { + if (!Payload.Invalid) Err = std::move(Message); + Payload.Invalid = true; + }; for (const RecordFieldDecl &Field : Fields) { const std::string &FieldName = Field.Name; const std::string &FieldTypeName = Field.TypeName; if (Payload.findField(FieldName)) { - Err = "Duplicate field '" + FieldName + "' in record " + Name; - return false; + Bad("Duplicate field '" + FieldName + "' in record " + Name); + continue; } const TypeInfo *FieldInfo = resolve(FieldTypeName); if (!FieldInfo) { - Err = "Unknown type " + FieldTypeName + " for field " + FieldName + - " of record " + Name; - return false; + Bad("Unknown type " + FieldTypeName + " for field " + FieldName + + " of record " + Name); + continue; } if (FieldInfo->isVoid()) { - Err = "Field " + FieldName + " of record " + Name + " cannot be VOID"; - return false; + Bad("Field " + FieldName + " of record " + Name + " cannot be VOID"); + continue; } // By-value record fields require a *completed* record (source order); // this also rules out self/mutual inclusion. Inclusion via a pointer // type is fine (opaque ptr, always complete). if (FieldInfo->isRecord() && llvm::cast<StructType>(FieldInfo->LLVMType)->isOpaque()) { - Err = "Record type " + FieldTypeName + " must be fully defined before field " + - FieldName + " of record " + Name + " (records cannot contain themselves)"; - return false; + Bad("Record type " + FieldTypeName + " must be fully defined before field " + + FieldName + " of record " + Name + " (records cannot contain themselves)"); + continue; } RecordFieldInfo FI; @@ -236,8 +242,9 @@ bool TypeSystem::defineRecord(const std::string &Name, } llvm::cast<StructType>(It->second.LLVMType)->setBody(FieldTypes); + bool Ok = !Payload.Invalid; It->second.Record = std::move(Payload); - return true; + return Ok; } bool TypeSystem::definePointer(const std::string &Name, |
