aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/CodeGen.cc4
-rw-r--r--lib/CodeGen/Designator.cc4
-rw-r--r--lib/CodeGen/TypeSystem.cc29
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,